# Is-odd-jev – check if a number is odd, with a calibrated probability

> Source: <https://github.com/alxcrt/is-odd-jev>
> Published: 2026-09-17 23:06:50+00:00

Check whether a number is odd, using a System One model, with a calibrated probability.

```
npm i is-odd-jev
js
const isOdd = require('is-odd-jev');

await isOdd(5);
// { odd: true, p: 0.999, ms: 71, output_tokens: 3 }

await isOdd(4);
// { odd: false, p: 0.002, ms: 88, output_tokens: 3 }
npx is-odd-jev 5
```

`is-odd` (2014) returns a boolean. It cannot tell you how sure it is.

`is-odd-ai` (2023) asks an LLM, which returns a string you then parse, and which will
happily invent a confidence score if you ask it for one.

`is-odd-jev` returns `p` — the model's actual probability that `n` is odd, computed
from the distribution rather than narrated. Jev's `Noul` primitive has no `confidence`
field, because the probability *is* the answer. If you need a symmetric certainty:

``` js
const { odd, p } = await isOdd(n);
const confidence = Math.abs(p - 0.5) * 2;
```

Which lets you do the thing you could never do with an LLM:

```
if (confidence >= 0.95) ship(odd);
else escalateToHuman(n);
```

Pick that threshold by measuring it on a held-out set, not by intuition.

Node 18+. Zero dependencies.

| env | default | 
|---|---|
| `TYPESAFE_API_KEY` | — | 
| `AI_GATEWAY_API_KEY` | — (fallback, see below) | 
| `TYPESAFE_BASE_URL` | `https://api.typesafe.ai` | 
| `TYPESAFE_DEFAULT_MODEL` | `jev-latest` | 

Direct TypeSafe keys are waitlisted. [Vercel AI Gateway](https://vercel.com/docs/ai-gateway)
serves the same model as `typesafe-ai/jev` with no waitlist, so this works instead:

```
export AI_GATEWAY_API_KEY=...
npx is-odd-jev 5
```

`TYPESAFE_API_KEY` wins if both are set. Two things genuinely differ through the gateway:

- **Probabilities come back rounded** , usually to 2dp — you get`0.99` , not`0.999` .
- **The free tier is rate-limited hard** on this model. Fine for one number, not for a loop.

Under the hood the gateway calls a `Noul` a `boolean` and its answer `probability`,
and takes the model in a header rather than the body. This package handles that; if
you are calling it yourself, `experimental_evaluate` from `ai@7` speaks it natively:

``` js
import { experimental_evaluate as evaluate } from 'ai';

const { answers } = await evaluate({
  model: 'typesafe-ai/jev',
  state: { n: 5 },
  questions: { odd: { type: 'boolean', instructions: 'Is n odd?' } },
});
{
  "model": "jev-latest",
  "state": { "n": 5 },
  "questions": { "odd": { "type": "noul", "instructions": "Is n odd?" } }
}
```

It cannot chat. It cannot explain itself. It cannot hallucinate. It can only tell you, with a calibrated probability, that five is odd.

Releases publish themselves from GitHub Actions via npm
[trusted publishing](https://docs.npmjs.com/trusted-publishers): the workflow swaps its
OIDC token for publish rights, so there is no npm token in the repo, no secret to
rotate, and no OTP prompt.

```
npm version patch && git push --follow-tags
gh release create v1.1.1 --generate-notes
```

Publishing the release fires [`.github/workflows/publish.yml`](https://github.com/alxcrt/is-odd-jev/blob/main/.github/workflows/publish.yml),
which runs the tests and then `npm publish`. The workflow upgrades npm first — OIDC
needs `npm >= 11.5.1` and the runner image ships something older, which is the kind of
thing that fails once and confuses you for an hour.

One-time setup, on npmjs.com: the package → Settings → Trusted Publisher → GitHub
Actions, repo `alxcrt/is-odd-jev`, workflow `publish.yml`.

- `is-odd` — depends on`is-number` .`is-even` depends on`is-odd` .
- `is-odd-ai` — asks GPT, parses the reply.
- `n % 2 === 1` — still correct, still 0 ms, still free.

MIT
