Pi
September 18, 2026 · View on GitHub
Pi · Jev Compaction
Keep the evidence. Let go of stale reads.
Decision-driven, extractive context compaction for Pi.
Quick start · How it works · Configuration · Verification · 简体中文
Long coding sessions accumulate old file reads, searches, and directory listings. Some still matter; others only occupy context. This extension asks Jev to judge complete read-only tool pairs, then uses ordinary code to remove pairs it rates as unnecessary. Everything retained is copied into an extractive transcript packet.
Jev does not write a summary. Pi's supported compaction API accepts a summary string, so this package puts the extractive packet in that field and preserves Pi's native recent-message boundary. It does not patch Pi, rewrite the session file, or pretend that Pi supports replacing arbitrary history messages.
Inspired by tamaratran/fast-jev-compaction, with a Pi-specific lifecycle adapter and conservative selection policy.
Quick start
Requires Node.js 22.19+ and Pi 0.84.2. That is the version actually validated; older Pi versions and the former @mariozechner package namespace are not claimed as supported.
pi install git:github.com/Wang-auspicious/pi-jev-compaction@v0.1.0
export TYPESAFE_API_KEY="your-typesafe-key"
pi
PowerShell:
pi install git:github.com/Wang-auspicious/pi-jev-compaction@v0.1.0
$env:TYPESAFE_API_KEY = "your-typesafe-key"
pi
In an existing Pi session, run /reload after installing, then /compact when you want to compact. Automatic threshold and overflow compaction use the same hook. Pi still needs a configured conversation model and its normal authentication: the host resolves summarization authentication before invoking extensions.
To try a local checkout:
pi -e ./extensions/index.ts
Or install a checkout with pi install /absolute/path/to/pi-jev-compaction. No npm publication is required. The release tarball is also a self-contained package: extract it, then install its package directory with pi install /absolute/path/to/package.
How it works
- Pi chooses the boundary.
session_before_compactsupplies the older messages, any split-turn prefix, previous summary, recent-message boundary, and abort signal. - Code determines eligibility. Only uniquely paired, successful
read,grep,find, andlscalls outside the protected recent span can be candidates. The full serialized call and result must fit within 8,000 UTF-8 bytes. - Jev judges the evidence. Each
noulquestion contains the complete candidate call and result, not just an ID or an output length. Shared state contains the latest three user instructions, latest three assistant text messages, previous summary, and/compactinstructions. It explicitly says that this is partial task context. - Code applies the result. A probability below
0.35removes the call and its result together. Higher values retain both. There is no output truncation and no generative summary step in the successful extension path. - Pi stores the packet. Retained records stay in chronological order in a JSON-lines transcript packet, alongside the previous summary verbatim. Pi appends its normal compaction entry and keeps every recent message from its original
firstKeptEntryIdonward.
The result includes byte counts, reduction, request count, elapsed time, pair decisions, and cumulative read/modified file lists in the compaction entry's details. The UI notification identifies either the extractive path or native fallback. Byte reduction is not an exact tokenizer measurement.
What is protected
| Content | Policy |
|---|---|
| User and assistant prose, constraints and textual to-do lists | Always retained in the replaced span |
| Previous compaction | Copied verbatim, including any older host-generated summary |
| Pi's recent-message tail | Native boundary is unchanged |
| Last six messages inside the older span | No tool-pair removal |
write, edit, bash, unknown tools | Always retained, even after a successful result |
| Unfinished, orphaned, duplicate-ID, out-of-order or failed tool calls | Retained; never candidates |
Read output with TODO, pending, unverified, [ ], or corresponding supported Chinese markers | Retained deterministically |
| Read pair larger than 8,000 bytes | Retained; incomplete evidence is never scored |
| Images or audio in the replaced span or recent state | Delegate to native compaction; do not silently discard media |
All potentially mutating tools are retained because a successful tool response is not independent verification that the user's intended change is correct. This deliberately reduces the number of opportunities to compact. The marker rule is a small deterministic guard, not a claim to understand every possible natural-language to-do in arbitrary tool output.
The extractive packet preserves the content of retained records; it changes their representation to historical text inside Pi's summary message. Original provider usage metadata is not copied into the packet. Dropping a read pair is intentionally lossy, and a probability is not a guarantee that its evidence will never matter again. Pi's original session records remain available in its session history.
Configuration
Set environment variables before starting Pi. Avoid committing keys to project settings or source files.
| Variable | Default | Meaning |
|---|---|---|
TYPESAFE_API_KEY | unset | Bearer credential for TypeSafe; missing key uses native compaction |
JEV_ENABLED | enabled | Set 0 to bypass the extension |
JEV_KEEP_THRESHOLD | 0.35 | Retain pairs with probability at or above this value; (0, 1]. Lower values retain more |
JEV_TIMEOUT_MS | 15000 | Total Jev deadline across all batches, integer 1–120000 |
JEV_MAX_OUTPUT_BYTES | 28000 | Extractive packet ceiling, additionally capped at Pi's reserveTokens using a conservative one-byte-per-token allowance |
JEV_ENDPOINT | https://api.typesafe.ai/v1/systemone | Endpoint override for a trusted proxy or local test server; receives the key and submitted content |
The API body is exactly the decision API shape:
{
"model": "jev-latest",
"state": { "recentUserInstructions": ["…"], "previousSummary": "…" },
"questions": {
"keep_0": {
"type": "noul",
"instructions": "Should this call and result be retained? Complete candidate evidence follows…"
}
}
}
The implementation reads answers.keep_0.noul, a finite probability in [0, 1]. It does not expect a separate confidence field.
Budgets and failure behavior
The documented Jev limits used for this implementation are 64k tokens for the total request and 32k for state plus the longest question. This package conservatively caps serialized UTF-8 bytes at 56,000 per full request and 28,000 for state plus one question and envelope allowance; state alone is capped at 16,000 bytes. These are conservative transport budgets, not tokenizer measurements or a promise of a fixed API cost. Questions are batched sequentially with one deadline, and each batch repeats the shared state.
| Condition | Result |
|---|---|
| Valid answers and at least 10% packet byte reduction | Save extractive compaction through Pi |
| Missing key, timeout, network error, 429, invalid JSON/probability | Return control to Pi's native compactor |
| No eligible reads, no useful reduction, state/output too large | Use native compaction |
| User cancels compaction | Return cancel: true; do not trigger a fallback model request |
| Disabled | Leave compaction to Pi |
Fallback may invoke Pi's configured generative model and incur its normal latency and cost. Native summaries follow Pi's own preservation policy, not the extension's extractive guarantees. If native compaction itself fails, Pi reports that failure. This extension never partially commits the decisions from a failed batch.
Recent instructions, prior summary, and eligible call/result contents are sent to TypeSafe when the extension runs. This is an online service, not local-only compaction. No API key is written into session details, and HTTP errors report a status rather than reflecting the service's response body.
Verification
npm ci
npm run check
npm pack
check runs unit tests, strict TypeScript checking against Pi 0.84.2, a real Pi smoke test, and a fixture benchmark. The smoke test installs the package with Pi's real CLI into isolated settings, loads it with Pi's real resource loader, invokes AgentSession.compact(), checks the stored compaction and preserved source records, and removes the isolated installation. Only Jev's HTTP server is mocked. No host LLM is called.
The fixture benchmark measures deterministic selection, protected content, pairing, and byte reduction. It does not measure Jev's semantic accuracy, live latency, cost, or later task success. No live API key was used for the initial release. See verification notes for the acceptance boundary and design notes for the integration contract.
Uninstall
pi remove git:github.com/Wang-auspicious/pi-jev-compaction@v0.1.0
For a local installation, pass the same local package path to pi remove. Run /reload or restart Pi. Existing extractive compaction entries remain usable as ordinary Pi summary text; original session history is unchanged. To temporarily bypass the extension, set JEV_ENABLED=0 before starting Pi.
Credits and license
The decision-first compaction idea and the explanation structure are inspired by fast-jev-compaction, reviewed at commit e3f262a, version 0.2.0, MIT. This is an independent implementation for Pi, not the upstream Claude Code hook and not an official Pi or TypeSafe integration.
The main differences are Pi's summary-slot contract, full candidate evidence, conservative read-only eligibility, strict probability validation, bounded requests, cancellation, and explicit fallback. See NOTICE and MIT License.