Small semantic functions on top of the TypeSafe Jev API.
Zero runtime dependencies, native fetch, strict TypeScript, ESM only (Node >= 20).
Every function makes probability judgments and keeps them honest: a network, API,
timeout, or malformed-response failure throws a JevError — it is never converted
into false or an empty result — and an uncertain judgment is never silently
treated as no.
npm install jevaisThe TYPESAFE_API_KEY environment variable is the default key source, or set it
once with configure():
import { configure } from 'jevais';
configure({ apiKey: process.env.TYPESAFE_API_KEY });Every function also accepts these options per call (per-call > configure() >
defaults):
| option | default | meaning |
|---|---|---|
apiKey |
TYPESAFE_API_KEY |
TypeSafe API key |
model |
"jev-latest" |
model id sent with every request |
timeoutMs |
30000 |
per-attempt request timeout |
retries |
3 |
retries on HTTP 429/529, exponential backoff, honors Retry-After |
One yes/no question over one state. Resolves true when P(yes) >= threshold
(default 0.85).
import { ifjev } from 'jevais';
if (await ifjev('user reacts angry', userResponse, 0.85)) {
// do thing
}The first item (original order) whose P(yes) >= threshold, or undefined.
One request per item with bounded concurrency (default 4), so completion order
never changes the result.
import { findMeaning } from 'jevais';
const match = await findMeaning(messages, 'the customer wants to cancel');
if (match) {
// offer the cancellation flow
}Splits items by P(yes): p >= threshold -> yes, p <= 1 - threshold -> no,
the rest -> uncertain. Uncertain stays explicit — never silently no.
import { partitionMeaning } from 'jevais';
const { yes, no, uncertain } = await partitionMeaning(
tickets,
'the customer explicitly requests a refund',
{ threshold: 0.85 },
);Orders items by a Score judgment using the identical 2-to-10-level rubric for every item; sorted by score descending, stable for ties. Returns the items only.
import { rankMeaning } from 'jevais';
const ranked = await rankMeaning(feedback, [
'irrelevant noise',
'minor, optional improvement',
'clear, actionable improvement',
'critical, must fix now',
]);Detects a substantive change between two states while ignoring rewording.
One Noul question over the structured state { before, after }.
import { changedMeaning } from 'jevais';
if (await changedMeaning(oldConfig, newConfig, 'deployment requirements changed')) {
// redeploy
}Like partitionMeaning, it accepts threshold through the options object
(default 0.85).
The raw JEV primitives behind the functions above. askNoul resolves the
probability itself (P(yes) in [0, 1]); askScore resolves the full Score
answer (score, confidence, legend, probabilities). Use these when you
need the number, not just the threshold decision.
import { askNoul, askScore } from 'jevais';
const p = await askNoul('Is this a bug?', 'I think this is an error');
if (p >= 0.4) {
// probable
}
const answer = await askScore('Rate this item.', ['low', 'high'], feedbackText);
console.log(answer.score, answer.probabilities);askNoul/askScore take the same per-call options as ifjev (apiKey,
model, timeoutMs, retries).
All failures throw JevError, which carries the HTTP status (when the failure
came from a response) and a raw body snippet:
import { JevError, ifjev } from 'jevais';
try {
await ifjev('user reacts angry', userResponse);
} catch (error) {
if (error instanceof JevError) {
console.error(`jev failed: ${error.status ?? 'network'} - ${error.message}`);
}
}HTTP 429/529 are retried up to retries times with exponential backoff (honoring
Retry-After when present); 401, 422, and everything else throw immediately.
Empty item arrays resolve with an empty result without calling the API.
- One request per item: every item is judged with its own minimal state, which keeps large, irrelevant state from distracting the judge.
- Keep questions literal, in English, and free of math/counting/date logic.
npm install
npm run lint
npm run typecheck
npm run build
npm testMIT