Package-level declarations
The whole public API: the question DSL, typed answers, the client, configuration and errors.
Types
JevApi as blocking calls, for scripts, main, and tests, reached through JevClient.blocking, or blocking for any other JevApi.
JevApi as blocking calls, for scripts, main, and tests. Every call declares InterruptedException, which runBlocking throws when the waiting thread is interrupted, so Java code can catch it.
Blocking calls are JVM-only; on Kotlin/Native, call the suspend API, wrapped in runBlocking if need be.
Blocking calls are JVM-only; on Kotlin/JS and Kotlin/Wasm, call the suspend API.
The answer to a Box: the box around the target, and a confidence from 0 to 1, or null when the API reports none. A Box always answers with a box, even when the target isn't in the image.
Find one thing in an image: the answer is a BoxAnswer, the box around it. Box takes no criteria, and needs an image attached to the request. It always returns a box, even for a target that isn't there, so ask a Noul too. Box needs Jev 1.14 (jev-preview or jev-1.14.0).
The answer to a Choice: the highest-probability option, the probability of every option, and a confidence from 0 to 1. Confidence is not the winner's probability, but it depends on nothing else: it rescales that probability so that an even split across the options is 0 and certainty is 1. A close runner-up therefore shows only in probabilities; compare the top two entries of ranked to catch a near-tie.
A Choice's options, in order. Option keys and descriptions are both sent to the model.
Marks jev4k's support for TypeSafe's images and Box questions. TypeSafe calls both "Dreamer-ready": the request format, the answers and the limits can change between its releases, so this API can change in any jev4k release. Opting in also stands for what TypeSafe's TypeSafe-Danger-Zone-Images: true header does: jev4k sends that header with every request that carries an image or a Box question.
401: the API key is missing or invalid.
400: the request was malformed.
Settings for single calls that override the client's own, as both official SDKs allow:
Builder for JevCallOptions. Every setting starts unset, which keeps the client's value. build reports every problem it finds at once, as JevConfigBuilder.build does.
A Jev client over Ktor, on the platform's default engine (CIO on the JVM) unless one is supplied. Configure it inline, or rely on TYPESAFE_API_KEY:
Resolved client settings. Build one with JevConfigBuilder or the JevClient { } constructor.
Builder for JevConfig. Each setting resolves as: explicit value, then environment variable, then default. String settings are trimmed, and a leading byte-order mark is dropped, so the trailing newline or the mark of a value read from a file is harmless, and a value that is blank after trimming counts as unset. build fails on a missing API key first, on its own, and otherwise reports every problem it finds at once, without echoing a secret.
The client could not be configured, e.g. no API key was supplied.
No complete HTTP response was received (DNS, TLS, a refused or dropped connection, a truncated body).
Environment variable names, defaults, and header names shared with the official TypeSafe SDKs.
Base class for every error raised by jev4k.
A PNG or JPEG image to send with a request.
5xx: a server-side failure.
404: unknown endpoint or resource.
529: TypeSafe is temporarily overloaded.
403: the API key may not do this.
429: rate limited. retryAfter is the server's hint, when it sent one.
A successful response was missing data or didn't match the questions asked; fieldPath locates the problem.
The answers to one request. Read them with the handles you declared (result[Triage.department]) or by id (result.noul("urgent")). A missing or mismatched answer raises JevResponseValidationException when it is read; an id or handle that wasn't part of the request raises IllegalArgumentException.
A request attempt timed out: the configured timeout, or, with a caller-supplied engine, that engine's own connect or socket timeout, which the message then names.
422: the request failed server-side validation; body names the offending field.
A request was rejected locally, before anything was sent. problems lists every issue found.
What GET /v1/models returned: the models, in the server's order, as a List<ModelInfo>, plus the call's requestId (the x-typesafe-request-id header). It equals any list holding the same models, whatever its request id, so a test can compare it with listOf(...).
The answer to a Noul: noul is the probability, from 0 to 1, that the answer is yes. Nouls have no confidence.
Optional descriptions of what a Noul's yes and no mean.
Collects the questions for one request, keyed by ids you choose. Every function returns a QuestionRef handle, so val urgent = noul(...) then result[urgent] works too.
What one question asks, independent of its id: instructions plus criteria, each arbitrary JSON (usually a string). Named after the TypeSafe JS SDK's Question / NoulQuestion / ChoiceQuestion / ScoreQuestion. A QuestionRef pairs one with an id.
Creates a question when it is bound to a JevQuery property, using the property name as the default id.
An ordered, validated set of questions: everything one request asks about a single state.
When and how failed requests are retried. The defaults match the official JS SDK: two retries, 0.5 s backoff doubling to a 5 s cap with up to 25% subtracted as jitter, and server retry-after-ms / Retry-After hints honored up to maxRetryAfter. The Python SDK shares the retries, backoff and statuses but doesn't cap hints, and adds a 30 s budget per call, which jev4k doesn't have: timeout applies per attempt.
The answer to a Score: score is the probability-weighted level (Σ level × p), so it can fall between levels. probabilities and legend are keyed by level number; the legend holds the level entries that were sent. levelCount is the number of levels asked about.
A Score's levels, lowest first. Describe situations, not degrees; each level is judged on its own.
Rate along ordered levels; a level's number is its index.
An answer of a type this version of jev4k doesn't know; raw is the answer object as received.
Properties
Functions
Asks a JevQuery's questions about a @Serializable state, with images attached after the query's own.
This API as blocking calls, for code that depends on a JevApi rather than a JevClient, so a fake or a withOptions view can be handed in. From Java: BlockingJevKt.blocking(api). The calls exist on the JVM only.
Builds a structured JSON entry for instructions, option descriptions, or levels, e.g. entry("question" to "Which team?", "focus" to "The primary request"). Keys keep their order, and the model sees both the keys and the values.
The JevApiException subclass the client raises for HTTP status, for testing a caller's error handling: 429 gives a JevRateLimitException, 401 a JevAuthenticationException, and so on.
The same, from the response body as JSON text. Text that isn't JSON, or isn't a JSON object, raises JevResponseValidationException, as it does from the client, so a garbled response can be simulated too. A leading byte-order mark is dropped, as the client drops one.
A JevResult built from a raw response body, as JevApi.evaluate would have returned it for questions.
Encodes a @Serializable value as JSON, keeping fields that equal their defaults.
Asks inline questions about a @Serializable state.
Asks inline questions about a text state.
Asks inline questions about a JSON state.
Builds a validated QuestionSet inline.
An image read now from file, with the same limit.
An image read now from path. A file over the API's 16 MiB limit isn't read: the image carries that problem instead. These are Kotlin extensions on the companion; from Java, which would have to pass the companion explicitly, write JevImage.of(Files.readAllBytes(path)).