English | 简体中文
A minimal, standalone Pi extension: it connects to a Jev API and registers a jev_evaluate tool supporting three structured judgment types — noul, choice, and score. It contains no tool routing, auto mode, skill discovery, or context compaction.
Install from a local checkout, or straight from GitHub:
pi install /path/to/pi-jev-core # local checkout
pi install git:github.com/morler/pi-jev-core # from GitHubOnce published to npm:
pi install npm:pi-jev-coreThis package ships pure TypeScript source, loaded by pi's extension loader (jiti). For programmatic use (via a loader such as tsx/jiti), import the entry point directly: import { JevClient } from "pi-jev-core". Deep imports (e.g. pi-jev-core/src/jev.ts) remain available when you only need one layer.
TypeSafe is the default. Set JEV_PLATFORM and provide the matching credential; credentials may also live in the secret files listed below under ~/.pi/agent/secrets/.
JEV_PLATFORM |
Credential env var | Pi secret file | Default model |
|---|---|---|---|
typesafe (default) |
TYPESAFE_API_KEY |
typesafe_api_key |
jev-latest |
openrouter |
OPENROUTER_API_KEY |
openrouter_api_key |
typesafe/jev-1.13 |
cloudflare |
CLOUDFLARE_API_TOKEN |
cloudflare_api_token |
typesafe/jev |
vercel |
AI_GATEWAY_API_KEY |
ai_gateway_api_key |
typesafe-ai/jev |
local |
JEV_LOCAL_PORT (port, no API key) |
— | jev-latest |
custom |
JEV_CUSTOM_ENDPOINT (+ optional JEV_CUSTOM_API_KEY) |
jev_custom_api_key |
JEV_CUSTOM_MODEL (optional, defaults to jev-latest) |
Cloudflare additionally requires CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_GATEWAY_ID. Use JEV_MODEL to override the model; the TypeSafe platform also honors TYPESAFE_DEFAULT_MODEL. Never commit API keys or send them to the model. |
|||
The local platform talks to a Jev API server on localhost: set the port with /jev-platform local <port> (persisted as localPort in the same config file) or JEV_LOCAL_PORT. It POSTs {model, state, questions} to http://127.0.0.1:<port>/v1/systemone and expects {answers, model?, usage?} back; no API key is required. |
|||
The custom platform talks to a Jev-compatible endpoint of your own. JEV_CUSTOM_ENDPOINT (or /jev-platform custom <endpoint-url> [model], which persists them as customEndpoint and customModel) is the URL that receives the request, used as given — so include the path (for example https://jev.example.com/v1/systemone). It POSTs {model, state, questions} there and expects {answers, model?, usage?} back — the local contract, plus Authorization: Bearer <key> when JEV_CUSTOM_API_KEY (or the jev_custom_api_key secret file) is set; the key is optional because a self-hosted endpoint may be open. The model resolves as JEV_MODEL, then JEV_CUSTOM_MODEL or the persisted customModel, then jev-latest. The endpoint has to be set before the platform can be switched to. |
Switch the active platform at runtime with the /jev-platform command: with no argument it lists every platform with its credential origin and marks the active one; /jev-platform <name> switches and persists (for local, /jev-platform local <port> also sets the port; for custom, /jev-platform custom <endpoint-url> [model] also sets both) the choice to ~/.pi/agent/pi-jev-core.json (path overridable via JEV_CONFIG_FILE); the /jev-platform log on|off switch persists to the same JSON file. Resolution order: JEV_PLATFORM env, then the persisted choice, then typesafe.
The tool sends a state plus multiple named questions to the active Jev platform and returns answers, the model, usage, elapsed time, and each provider's raw answer. Question types:
noul: a yes/no judgment; returns the probability of yes.choice: picks from candidates in thecriteriaobject; keys are option IDs, values are descriptions.score: rates along thecriteriaarray, listed from lowest to highest level; at least two levels (the array index is the score, starting at 0 — the response'slegendfield mirrors this mapping).
Example request:
{
"state": {
"change": "Added a required field to the public request type"
},
"questions": {
"breaking": {
"type": "noul",
"instructions": "Does `change` break an existing caller?"
},
"kind": {
"type": "choice",
"instructions": "What best describes `change`?",
"criteria": {
"api": "Public API change",
"bug": "Bug fix",
"other": "Other"
}
},
"severity": {
"type": "score",
"instructions": "Rate the impact of `change`",
"criteria": ["Critical", "High", "Medium", "Low"]
}
}
}state may be a string or a JSON object. For object state, each question must reference the fields it needs with backticks, such as `change`; missing or unsafe paths are rejected. String state is sent as the text field for compatibility. One request can carry multiple independent questions. noul needs no criteria. Only referenced object fields are transmitted to the configured platform.
The repo ships the building-with-jev agent skill at skills/building-with-jev/SKILL.md, adapted from dbreunig/building-with-jev-skill (which targets the Python typesafe_sdk) to this package's API. It covers question design for noul/choice/score, minimal-state construction, confidence-gated composition patterns, and a symptom → cause → fix table for wrong or low-confidence answers.
Adaptations from upstream:
- All examples use
JevClient.evaluate/jev_evaluate; answers are read uniformly via.value(the choice label, or the score/noul number), with.distributionfor the full probability spread. instructionsaccepts a string only — the upstream object/array form (question/focus/inspectkeys) is inlined as sentences; extendingsrc/types.tsandsrc/jev.tsis the documented upgrade path.- Noul
true/falsecriteria are not passed through (noul(instructions)takes the question only); when the boundary is subtle, state both sides inside the instruction. - Optional-field guard pattern:
value/confidencecan beundefinedwhen the provider gave no answer — route missing answers to a fallback instead of coercing them to0, and use the exportednoulProbability(raw)to tell "no answer" apart from "answered 0".
All three adaptations were verified against live responses (model jev-1.13.0): choice/score carry confidence while noul does not, and a score's value is the probability-weighted mean of the level indexes.
Install the skill for your agent:
cp -r skills/building-with-jev ~/.pi/agent/skills/npm install
npm test
npm run typecheckThe API client and platform adapters are extracted and trimmed from the MIT-licensed pi-jev; see LICENSE for the original notice.