# Configuration

> Zero-config with an API key, configureSemantic for the module-level instance, createSemantic for a private one, and every default you can set.

Section: Getting started · HTML: https://jevascript.org/docs/configuration · Markdown: https://jevascript.org/docs/configuration.md

## Zero configuration

If `JEV_API_KEY` is set, the module-level `semantic` builds a Jev provider on first use. Nothing else is required.

```ts
import { semantic } from "jevascript"

await semantic(text).is("This is a complaint.")   // works with only the key in the environment
```

Without a key and without a configured provider, the first call throws `NotConfiguredError` with a message that says exactly that.

## Two ways to configure

### `configureSemantic()` — the module-level instance

Merges configuration into the global runtime. Calling it twice merges twice; it never replaces what was there.

```ts
import { configureSemantic, jev } from "jevascript"

configureSemantic({
  provider: jev({ model: "jev-1.13.0" }),
  defaults: { timeoutMs: 5_000 },
})
```

Good for scripts and quick starts. `resetSemantic()` clears it and starts a fresh in-memory cache, which test suites use between cases.

### `createSemantic()` — a private instance

Returns an instance with its own provider, cache, defaults and hooks. It never touches the global one, so two instances can coexist: a fast one and a careful one, or one per tenant.

```ts
// lib/semantic.ts
import { createSemantic, jev } from "jevascript"

export const semantic = createSemantic({
  provider: jev(),
  defaults: { timeoutMs: 5_000, cache: "10m" },
  observability: {
    onEvaluation: (e) => metrics.observe("semantic", e.latencyMs),
  },
})
```

An instance exposes `semantic.config` (read-only) and `semantic.configure(partial)`, which merges the same way `configureSemantic` does. Tests use it to swap the provider:

```ts
semantic.configure({ provider: createMockSemanticProvider({ urgently: 0.9 }) })
```

> **Tip:** Use `createSemantic` in applications, `configureSemantic` in scripts. Application code that imports `semantic` from your own module reads exactly like the quick start; only the import line differs.

## `SemanticConfig`

| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `provider` | `SemanticProvider` | — | The model adapter. Defaults to `jev()` built from the environment when `JEV_API_KEY` is set. See [Providers](https://jevascript.org/docs/providers). |
| `defaults` | `SemanticDefaults` | — | Per-call defaults, listed below. Any call option overrides them. |
| `observability` | `Observability` | — | `onEvaluation` and `onUnbatched` hooks. See [Observability](https://jevascript.org/docs/observability). |
| `cacheStore` | `SemanticCache` | `new MemoryCache()` | Where cached answers live. Implement the two-method interface to use Redis or similar. See [Caching](https://jevascript.org/docs/caching). |
| `warnUnbatched` | `boolean` | `NODE_ENV !== "production"` | Warn once when a context issues a second request that could have been batched. |

## `SemanticDefaults`

| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `timeoutMs` | `number` | `10_000` | Per-request timeout. When several questions share a request, the largest timeout among them applies. |
| `cache` | `string \| number` | — | Cache TTL for every answer: `"5m"`, `"1h"`, `"250ms"`, or milliseconds. Unset means no caching. |
| `samples` | `number` | `3` | Rounds used to measure confidence when `minConfidence` is requested on a truth-backed question. |
| `minConfidence` | `number` | — | Reject answers whose measured confidence is below this unless a `fallback` is given. See [Uncertainty](https://jevascript.org/docs/uncertainty). |
| `threshold` | `number` | `0.5` | Probability above which `is()` reads as `true`. |
| `uncertaintyBand` | `[number, number]` | `[0.3, 0.7]` | Probabilities inside this band are reported as `"unknown"` when `allowUnknown` is set. |
| `scoreFrame` | `(criterion: string) => string` | `c => `This has high ${c}.`` | How a noun-phrase `score("urgency")` becomes a proposition. Replace it for other languages. |

Precedence is the same everywhere: **call options** win over **instance defaults**, which win over the **built-in defaults** above.

```ts
const semantic = createSemantic({ defaults: { threshold: 0.6 } })

await semantic(x).is("...")                       // threshold 0.6
await semantic(x).is("...", { threshold: 0.8 })   // threshold 0.8
```

## Environment variables

| Variable | Read by | Effect |
|---|---|---|
| `JEV_API_KEY` | `jev()` and the zero-config path | The API key. Its presence alone enables the module-level instance. |
| `JEV_MODEL` | `jev()` | Overrides the pinned default model. |
| `JEV_BASE_URL` | `jev()` | Overrides the API endpoint. Trailing slashes are stripped. |
| `NODE_ENV` | `warnUnbatched` | The unbatched warning is off when this is `"production"`. |

Explicit `jev({ ... })` options win over the environment, which wins over the built-in defaults.

## Reading the current configuration

```ts
import { getConfig, BUILTIN_DEFAULTS } from "jevascript"

getConfig()          // the module-level config as it stands
BUILTIN_DEFAULTS     // { timeoutMs: 10_000, samples: 3, threshold: 0.5, uncertaintyBand: [0.3, 0.7] }
semantic.config      // the config of a createSemantic() instance
```
