@danypops/pi-process-harness
v0.1.1
Published
Spawns real `pi` processes (and companion daemons) for integration tests that need a real AgentSession genuinely deciding to call a tool -- scripted via Pi's own first-party faux model provider, no live LLM call. The sibling of @danypops/pi-extension-harn
Downloads
61
Maintainers
Readme
@danypops/pi-process-harness
Spawns real pi processes (and companion daemon processes) for integration
tests that need more than @danypops/pi-extension-harness's
in-process/jiti/mock-cli layers can give: a genuine AgentSession deciding,
on its own, to call a tool from a prompt -- not a test hand-feeding a tool
name directly.
Why this exists
pi-extension-harness is explicit about its own boundary: it never boots a
real AgentSession or a real LLM. That's the right call for testing one
extension's own callback behavior in isolation, but it means nothing in that
package can prove "a real agent loop, given this prompt, actually calls this
tool" -- or coordinate a companion daemon process (a Vehicle-backed daemon,
for instance) alongside a real Pi process for a true end-to-end test.
This package covers exactly that gap, using Pi's own first-party scriptable
model provider (@earendil-works/pi-ai's fauxProvider) so the agent loop's
tool-call decision is real but deterministic -- no live LLM call, no API
spend.
Usage
import { spawnRealPiProcess, resolveFauxProviderExtensionPath, encodeFauxScript, SCRIPT_ENV_VAR, waitForRpcEvent } from "@danypops/pi-process-harness";
const proc = spawnRealPiProcess({
extensions: [resolveFauxProviderExtensionPath(), "/abs/path/to/your/extension.ts"],
extraArgs: ["--provider", "faux", "--model", "faux-1"],
env: {
[SCRIPT_ENV_VAR]: encodeFauxScript([{ type: "toolCall", name: "your_tool", arguments: { foo: "bar" } }]),
},
});
const events: unknown[] = [];
proc.onEvent((event) => events.push(event));
proc.sendPrompt("go");
await waitForRpcEvent(events, (event) => event.type === "tool_execution_end");
proc.dispose();For a companion daemon (Epi, or any other real process a test needs alongside the Pi process):
import { spawnCompanionDaemon } from "@danypops/pi-process-harness";
const daemon = await spawnCompanionDaemon({
command: "node",
args: ["dist/cli.js", "serve"],
isReady: async () => fs.existsSync("/tmp/my-daemon/handle.json"),
});
// ... drive the test ...
await daemon.dispose();What this does not do
- No sandboxing/isolation of the spawned process -- it's a real child
process on this machine with real filesystem/network access, same as any
other
child_process.spawn. - No assertion helpers beyond
waitForRpcEvent-- read the real RPC event stream and assert on it directly. - Not a replacement for
pi-extension-harness-- use that for fast, hermetic, single-extension behavior tests; reach for this only when a test genuinely needs a real agent loop or a real companion process.
License
MIT
