fast-jev-compaction-pi
Verbatim Jev-guided context compaction for pi: replaces the built-in compaction summary with fast-jev-compaction decisions — stale tool calls/results are dropped or truncated, everything kept stays verbatim.
Package details
Install fast-jev-compaction-pi from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:fast-jev-compaction-pi- Package
fast-jev-compaction-pi- Version
0.6.0- Published
- Sep 19, 2026
- Downloads
- 333/mo · 333/wk
- Author
- zaycruz_
- License
- MIT
- Types
- extension
- Size
- 89.8 KB
- Dependencies
- 0 dependencies · 0 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
fast-jev-compaction for pi
A pi extension version of tamaratran/fast-jev-compaction — the Claude Code plugin that replaces the compaction summary with Jev decisions: every tool call and result of the summarized span is scored in fast requests, stale ones are dropped or truncated, and everything kept stays verbatim. User and assistant text is never rewritten or summarized.
What and why
Most context compaction asks an LLM to summarize old turns. A summary is
lossy: a file path, exact error, constraint, or command can disappear even
when it matters later. This extension never rewrites anything. It hooks pi's
session_before_compact event, asks TypeSafe's Jev model — over the whole
conversation, with tool results omitted — which tool calls and results are
still needed, and replaces the LLM summary with a verbatim transcript of what
survived:
- tool calls Jev says no longer matter are removed together with their results;
- results whose contents are stale but whose call still matters are truncated
to their first
truncateHeadCharscharacters plus a note ([fast-jev-compaction truncated N chars of this tool result; re-run the tool if needed]); - everything else — user prompts, assistant text, kept calls and results — stays verbatim and in order.
The compacted transcript is stored as JSON in the compaction entry's
details.fastJev.messages, so the next compaction re-decides over the
accumulated pruned transcript instead of re-summarizing a summary —
compaction stays continuous and lossless-with-deletions across sessions.
Install
# from the npm registry (pinned to the published version)
pi install npm:fast-jev-compaction-pi@0.1.1
# or from this repo
pi install git:github.com/zaycruz/fast-jev-compaction-pi@v0.1.1
pi install git:github.com/zaycruz/fast-jev-compaction-pi # track main
# project-only (written to .pi/settings.json, shared with your team)
pi install -l git:github.com/zaycruz/fast-jev-compaction-pi
Try it without installing (temp checkout, current run only):
pi -e npm:fast-jev-compaction-pi
pi -e git:github.com/zaycruz/fast-jev-compaction-pi
Then run /fast-jev-status in any session to confirm it loaded and see the
resolved configuration. Updates: pi update --extensions (unpinned installs)
or pi install git:github.com/zaycruz/fast-jev-compaction-pi@vX.Y.Z (move a
pinned ref).
Manual install also works — copy or symlink this directory into pi's
extension folder (~/.pi/agent/extensions/ global, .pi/extensions/
project). No npm install is needed at runtime: the extension has zero
runtime dependencies (the fast-jev core library is vendored under vendor/),
and pi serves @earendil-works/pi-coding-agent itself.
Security: extensions run with your full system permissions. Review the source before installing — it is small:
index.ts+lib/(5 files) plus the vendored upstream core undervendor/.
Configure
The API key comes from the config files or the environment:
export TYPESAFE_API_KEY=...
Optional settings live in ~/.pi/agent/fast-jev-compaction.json (global) or
<project>/.pi/fast-jev-compaction.json (project, wins):
{
"apiKey": "…",
"model": "jev-latest",
"baseUrl": "https://api.typesafe.ai/v1/systemone",
"keepThreshold": 0.5,
"preserveRecentMessages": 0,
"maxStateTokens": 25000,
"maxRequestTokens": 30000,
"truncateHeadChars": 300,
"minReductionRatio": 0.25,
"requestTimeoutMs": 120000,
"goal": "optional standing task description",
"preserveCallInputs": true,
"preserveErrorTails": 1200,
"inputRetention": "always",
"inputRetentionThreshold": 0.2,
"routing": "reactive",
"routingThreshold": 0.5
}
| Option | Default | Meaning |
|---|---|---|
apiKey |
TYPESAFE_API_KEY |
TypeSafe API key |
model |
jev-latest |
Jev model name |
baseUrl |
https://api.typesafe.ai/v1/systemone |
System One endpoint |
keepThreshold |
0.5 |
Minimum keep probability for a call or result to stay |
preserveRecentMessages |
0¹ |
Newest messages of the summarized span pinned from scoring |
maxStateTokens |
25000 |
Estimated token ceiling for the state |
maxRequestTokens |
30000 |
Estimated ceiling for state plus one batch of questions |
truncateHeadChars |
300 |
Characters of a dropped result retained before the note |
minReductionRatio |
0.25 |
Minimum character reduction on the span required to replace the built-in summary |
requestTimeoutMs |
120000 |
Per-request timeout; 0 disables it |
goal |
derived | Ongoing task description; otherwise the last user prompts |
¹ Unlike the Claude Code plugin (default 6), pi's keepRecentTokens cut
already keeps the newest messages out of the summarized span entirely, so the
adapter pins nothing extra by default.
Run /fast-jev-status in a session to print the resolved configuration and
the outcome of the last compaction.
Behavior
- Triggers. Works for auto-compaction (context threshold),
/compact, and overflow recovery./compactwith focus instructions defers to pi's built-in summary — instructions ask for a summary, which is exactly what this extension does not produce; without instructions the verbatim path runs. - Fallback. Missing API key, Jev errors, timeouts, unfittable histories,
and spans where Jev's decisions reduce less than
minReductionRatioall decline: pi's built-in LLM summary runs instead. Nothing is ever half-applied. - Pinning. The first message of the transcript and the newest
preserveRecentMessagesof the span are never candidates, mirroring upstream. - Continuity. The pruned transcript persists in
details.fastJev.messagesand is re-scored together with each new span. If the latest compaction was pi's built-in one, its summary text is carried verbatim as a pinned message instead, so switching between engines never loses context. - Bookkeeping. Jev's token usage is recorded on the entry (pi's
Usageshape, cost zeroed), anddetails.readFiles/details.modifiedFileskeep pi's cumulative file tracking working across mixed compactions. - Session size.
detailsstores the pruned transcript as JSON in addition to the rendered summary text, roughly doubling the compacted span's bytes in the session file. That redundancy is what makes lossless continuation possible.
Differences from the Claude Code plugin
| Claude Code plugin | pi extension | |
|---|---|---|
| Integration | session.compact hook replaces the whole transcript |
session_before_compact replaces the summarized span with a rendered transcript; pi keeps the recent tail itself |
| Auto trigger | turn.complete + compactAtPercent |
pi's native threshold (compaction.reserveTokens) — no reimplementation needed |
| Re-compaction | pruned transcript persists as session messages | pruned transcript persists in details.fastJev.messages and is re-decided each time |
| Repeated-request state | whole transcript refitted each time | same (plus the carried previous transcript) |
| Branch summaries | — | untouched (out of scope, as upstream) |
The vendored core (vendor/fast-jev/) is upstream's src/ copied
unmodified; see vendor/README.md.
Does it actually help? (benchmark)
bench/ measures fast-jev against pi's built-in summary compaction on
identical seeded sessions with planted "memory markers" — real
typesafe-ai/jev through the Vercel AI Gateway for the extension, and the
real session model (zap/glm-5.3-flash-sglang) for the built-in arm. Results
at large (~27k-token context; full tables and method in
bench/README.md):
| fast-jev pure | fast-jev tuned | built-in summary | |
|---|---|---|---|
| compaction wall | 0.44 s | 0.45 s | 24.7–117 s |
| compaction tokens | 9.5 k | 9.5 k | 23.0 k |
| context after | 999 tok | 5,171 tok | 1,542–1,612 tok |
| exact commands + paths kept | 0 (Jev prunes) | 8/8 + 17/17 | 0/8 + 17/17 |
| deep error codes kept | 0/3 | 2/3 (real text + stack) | 2/3 (paraphrase, nondeterministic) |
| memory QA (3 questions/session) | 3/8 | 6/8 | 6/8 |
The honest read: real Jev makes compaction ~50× faster and cheaper than an
LLM summary. Pure mode gives the smallest context but drops old tool calls
(Jev's bet: outputs are re-derivable). The recommended tuning —
preserveCallInputs: true + preserveErrorTails: 1200 — keeps one-line
records of dropped calls and the tails of failing results: every exact
command, path, and error code survives with real text and stack, memory QA
ties the built-in summary, and compaction stays ~50× faster. routing: "jev" asks Jev one question over a statistical digest of the
span before scoring: scored pruning vs the native summary. On the benchmark
spans it routes to scored pruning with probability 0.74-0.75 and adds about
0.2 s; spans with no tool results skip the router entirely and go native
for free. routing: "reactive" (default) keeps the current behavior: score
first, decline to native when the reduction is too small.
inputRetention: "jev" additionally asks Jev per call whether the input
itself is worth keeping — it discriminates routine from fact-bearing calls
(routine inputs score 0.12–0.15, facts 0.20–0.29) and shrinks context
further, at the price of probabilistic retention. Caveats and an adversarial
review of the benchmark itself:
bench/ADVERSARIAL-REVIEW.md. Run it yourself
with BENCH_JEV_REAL=1 node bench/run-bench.mjs small medium large.
Development
npm install # dev deps: typescript, vitest, pi-coding-agent (types + convertToLlm)
npm run typecheck
npm test # unit tests, ported from upstream plus adapter tests, no network
npm run e2e # seeds a session, runs a mock Jev server, drives pi --mode rpc through compaction
The e2e script accepts scenarios: bash e2e/run.sh [callP resultP [second]]
— e.g. bash e2e/run.sh 0.05 0.05 (drop whole calls), bash e2e/run.sh 0.95 0.05 second (two compactions across pi restarts to prove continuity), and
MOCK_FAIL=500 bash e2e/run.sh (Jev failure → fallback). It uses a temp
directory, a mock server on localhost, and never touches a real API.
License
MIT — the vendored core is tamaratran/fast-jev-compaction by Tamara Tran (MIT).