Repository navigation
Releases: AboveColin/jevclient
Release list
1.3.1
An error now carries the API's message, not the whole JSON body.
- Before:
the request was rejected as invalid: {"detail":{"error_type":"api_usage_error","message":"Invalid request."}} - After:
the request was rejected as invalid: Invalid request.
The client reads detail.message (TypeSafe, measured on 2026-10-16 for a 400 and a 401), error.message (OpenRouter, measured on 2026-10-16 for a 401), or a string detail. Any other body, such as a proxy's HTML page, still comes through as it was, cut at 400 characters.
The prefixes HTTP {status}: , the API key was rejected: , rate limited: and the others do not change.
1.3.0
Images and Box questions, for Jev 1.14.
Image(data, format)is a PNG or JPEG. Pass images toask(..., assets={ref: Image(...)})and writerefwhere the image belongs: in the state, an instruction or a criterion.askraisesValueErrorbefore the request when an asset is not referenced anywhere, because the API answers that with a 400.Box(instructions)asks where something is. The answer is aBoxAnswerwithtop,bottom,left,rightas fractions of the image, andconfidence. Box needsjev-1.14.0orjev-preview.- The client sends the
TypeSafe-Danger-Zone-Images: trueheader on a request with an image or a Box, and on no other. JevError.statuscarries the HTTP status. 400, 413 and 422 raiseJevValidationError, sojev-nopenow raisesJevValidationError("Unknown model: jev-nope")instead of a generic error.MIN_IMAGE_SIDE(280),MAX_IMAGE_SIDE(1568) andMAX_IMAGE_BYTES(16 MiB) are the API's limits. The API refuses an image outside them and does not resize it.
Measured on 2026-10-16: an image is billed 2 input tokens for each 28 x 28 pixel square, so 200 at 280 x 280 and 6,272 at 1568 x 1568. A Box on a red square at 0.6/0.2/0.8/0.5 answered 0.59/0.19/0.79/0.50 at confidence 0.96.
1.2.0
An empty api_key sends no Authorization header.
Bearer with nothing after it is not a credential, so an endpoint that parses
the header answers 400 or 401 to it. A client built with JevClient("") now
leaves the header off the request, which is what an endpoint that asks for no
credential expects. A non-empty key is unchanged.
Measured against a local server: "a-real-key" sends Bearer a-real-key, ""
sends no Authorization header.
1.1.0
First release.
An async Python client for TypeSafe Jev, the System One decision model. Ask typed
questions about a piece of text and get values back rather than prose: a probability
for a yes/no question, one option out of a set with the whole distribution, or a
rating against levels you describe.
- Three question types, mixable in one request.
instructionsand every criteria value accept a string, an object or an array,
because the model reads JSON field names as labels.- A choice takes 2 to 255 options and a score takes 2 to 10 levels, both checked
locally so a mistake costs no request. ScoreAnswer.normalizeddivides by the rubric's own top level, which is what a
weighted composite needs.- One exception class per documented status code, and no internal retry loop, so the
caller owns the policy.
Measured from the Netherlands: three questions took 712 ms and a hundred took 714 ms,
so batching questions into one call is nearly free in time. Question text is billed
as input at roughly 38 tokens each, so it is not free in money.