{"_id":"@asqav/pi","name":"@asqav/pi","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@asqav/pi","version":"0.1.0","description":"Asqav extension for the pi coding agent - sign and gate tool calls before they execute","keywords":["pi-package","asqav","pi","coding-agent","ai-governance","tool-calling","audit-trail"],"license":"MIT","author":{"name":"Asqav","email":"info@asqav.com"},"homepage":"https://asqav.com","repository":{"type":"git","url":"git+https://github.com/jagmarques/asqav-pi.git"},"type":"module","pi":{"extensions":["./extensions"]},"scripts":{"test":"vitest run","lint":"tsc --noEmit"},"engines":{"node":">=18"},"dependencies":{"@asqav/sdk":"^0.5.13"},"devDependencies":{"@types/node":"^22.0.0","typescript":"^5.5.0","vitest":"^4.1.5"},"_id":"@asqav/pi@0.1.0","gitHead":"40e4829e120f52846b2f8d51ecbb2c8c8c59b1e2","bugs":{"url":"https://github.com/jagmarques/asqav-pi/issues"},"_nodeVersion":"22.22.0","_npmVersion":"10.9.4","dist":{"integrity":"sha512-kwtUVrdKoBsL3zfbJ4kCcU2NDJmXaGPI3yxGhwiEaYblHNNTMAxGVG1d3uNpAe6ZDUzJc//b3u/TRlo4AeLOuw==","shasum":"ed26e8f386402227a5192f90c2d75174307f13c4","tarball":"https://registry.npmjs.org/@asqav/pi/-/pi-0.1.0.tgz","fileCount":4,"unpackedSize":15422,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDbMWtNd86lnyfVY4KLwUwItFQwQhIOlOVrrZcNTc4GowIhAP9Eu06SD+CZUN3gciBV6dtyhzGBjjs2B84lbF4WSPiA"}]},"_npmUser":{"name":"jagmarques","email":"joaoagm90@gmail.com"},"directories":{},"maintainers":[{"name":"jagmarques","email":"joaoagm90@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pi_0.1.0_1782777369465_0.2553386750328188"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-29T23:56:09.235Z","0.1.0":"2026-06-29T23:56:09.609Z","modified":"2026-06-29T23:56:09.855Z"},"maintainers":[{"name":"jagmarques","email":"joaoagm90@gmail.com"}],"description":"Asqav extension for the pi coding agent - sign and gate tool calls before they execute","homepage":"https://asqav.com","keywords":["pi-package","asqav","pi","coding-agent","ai-governance","tool-calling","audit-trail"],"repository":{"type":"git","url":"git+https://github.com/jagmarques/asqav-pi.git"},"author":{"name":"Asqav","email":"info@asqav.com"},"bugs":{"url":"https://github.com/jagmarques/asqav-pi/issues"},"license":"MIT","readme":"<p align=\"center\">\n  <a href=\"https://asqav.com\"><img src=\"https://asqav.com/logo-text-white.png\" alt=\"Asqav\" width=\"150\"></a>\n</p>\n\n# @asqav/pi\n\nStop a rogue agent before it acts, and prove what it tried. This package is an extension for the [pi coding agent](https://pi.dev) that guards pi's tool calls with Asqav. It signs the intended tool call before the tool runs, and blocks the call when Asqav refuses. Every `bash`, `write`, and `edit` your coding agent attempts becomes a tamper-evident receipt, signed server-side with NIST FIPS 204 ML-DSA-65. The agent never holds the signing key, so it cannot forge the record.\n\nAsqav governs the agents you wire through it. An agent that never routes through the governed path produces no receipt and is not detected.\n\nThis is a pre-execution gate. The extension subscribes to pi's `tool_call` event, which fires before the tool executes and can block, signs `tool:start`, and returns a block when a call is refused so the tool never runs. After execution it signs a matching `tool:end` receipt with the outcome.\n\n## How it hooks in\n\nPi extensions are TypeScript modules that subscribe to lifecycle events. The `tool_call` event fires after `tool_execution_start` and before the tool executes, and a handler may return `{ block: true, reason }` to stop the tool. The `tool_result` event fires after execution. This extension uses exactly those two events and nothing else, so it stays out of the way of your other extensions.\n\nReferences, cold-verified:\n- [Extensions](https://pi.dev/docs/latest/extensions), covering `tool_call` (\"Can block\") and `tool_result`\n- [Pi packages](https://pi.dev/docs/latest/packages), covering the `pi` manifest and install sources\n\n## asqav Pi (locked distribution)\n\nWant Pi governed by default, in every process including sub-agents? Run the locked\ndistribution: upstream Pi + `@asqav/pi` installed globally + fail-closed. It is not a\nfork. See [docs/asqav-pi-distribution.md](docs/asqav-pi-distribution.md) and run:\n\n```bash\nscripts/install-asqav-pi.sh --help\n```\n\n## Install\n\n```bash\npi install npm:@asqav/pi\n```\n\nPi can also install straight from GitHub:\n\n```bash\npi install git:github.com/jagmarques/asqav-pi\n```\n\nPi runs `npm install` for the package, which pulls in the `@asqav/sdk` dependency automatically.\n\n## Setup\n\nSet your Asqav API key and run pi as usual:\n\n```bash\nexport ASQAV_API_KEY=\"sk_...\"\npi\n```\n\nEvery tool call pi makes now produces signed `tool:start` and `tool:end` receipts through the Asqav API. Governance is intended once the extension loads, so if it cannot initialize (no `ASQAV_API_KEY`, or the signer is unreachable at startup) it fails closed and blocks every tool call rather than letting pi run ungoverned. Opt out deliberately with `ASQAV_FAIL_OPEN=true`.\n\nEnvironment options:\n\n- `ASQAV_AGENT_NAME`: the agent name on receipts. Defaults to `pi`.\n- `ASQAV_OBSERVE_ONLY=true`: sign everything, never block. This only takes effect once init succeeds; if init fails the fail-closed default still blocks every tool (use `ASQAV_FAIL_OPEN=true` for audit-only setups that must keep running through a startup signer outage).\n- `ASQAV_FAIL_CLOSED=true`: block tools when Asqav is unreachable mid-session (a signing transport error). The default here is fail-open so a transient outage never breaks a working coding agent. A real deny always blocks regardless.\n- `ASQAV_FAIL_OPEN=true` (or `ASQAV_FAIL_CLOSED=false`): deliberate dev opt-out that restores the old inactive/allow behavior when init fails. Pi runs ungoverned, so use it only when you know that is what you want.\n\n## Programmatic use\n\nWhen embedding pi via its SDK, or when you want full control over the agent identity and options, register the extension yourself:\n\n```ts\nimport { init, Agent } from \"@asqav/sdk\";\nimport { registerAsqav } from \"@asqav/pi/extensions/asqav.ts\";\n\ninit({ apiKey: process.env.ASQAV_API_KEY! });\nconst agent = await Agent.create({ name: \"ci-coding-agent\" });\n\nregisterAsqav(pi, {\n  agent,\n  tools: [\"bash\", \"write\", \"edit\"],\n  failClosed: true,\n});\n```\n\n`registerAsqav(pi, options)` accepts:\n\n- `agent`, required: a pre-built Asqav `Agent` from `@asqav/sdk`.\n- `block`, defaulting to `true`: when a preflight is refused, block the tool. Set `false` for observe-only signing.\n- `tools`: only sign these tool names. Defaults to all tools.\n- `signResults`, defaulting to `true`: sign a `tool:end` receipt after each tool runs.\n- `preflight`: a custom `(actionType, input) => { allowed, reason }` check. Defaults to `agent.preflight`, which checks revocation, suspension, and active policies.\n- `failClosed`, defaulting to `false`: when a signing transport error occurs, block the tool.\n- `onError`: sink for signing transport errors. Defaults to `console.warn`.\n\n## How blocking works\n\nWhen the extension blocks, it returns `{ block: true, reason }` from the `tool_call` handler. Pi surfaces the block to the model as a failed tool call, so the model sees why and can react. The receipt for the refused call records `policy_decision: \"deny\"`, giving you proof of what the agent tried.\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-ca6506c3eec527385ec850f7b5bf98ea"}