Skip to content

@hawkeyexl/inference

Send a system prompt, a user prompt, and a JSON Schema. Get back JSON that validates against that schema, or a recorded error.

One narrow thing, deliberately:

(system, user, schema, temperature) -> JSON

No streaming. No multi-turn. No tool loops. If you need a conversation, this is the wrong package — that is worth knowing in the next thirty seconds rather than after an afternoon. Widening the provider contract requires an ADR, because every consumer pays for surface area added here.

Four providers, one call shape

Anthropic, any OpenAI-compatible server, the Claude CLI, and in-process llama.cpp. Swapping is a one-line change.

Validation with a retry

Ajv-checked against your schema. One retry, then an honest failure — never a throw, never a coerced value.

A cache you control

Content-addressed, human-inspectable on disk. You compose the key, because only you know what should invalidate an entry.

Cost that never guesses

An unknown model prices as undefined, not as a number someone made up. Budget gates depend on that distinction.

  • Node 24 or later, declared in engines — an older version gets an EBADENGINE warning from npm, not a refusal, and a second warning from the library on first use.
  • ESM only. require() fails with ERR_PACKAGE_PATH_NOT_EXPORTED; from CommonJS, use a dynamic import.
  • Three runtime dependencies, plus one optional peer dependency for local models.
Terminal window
npm install @hawkeyexl/inference

Everything exports from the package root.

  • Completion — the provider contract, five providers, a content-addressed cache, a price table, and a validate-and-retry wrapper. This is all structured extraction needs.
  • Judge — a canonical verdict schema, an N-run ensemble, consensus math, and confidence-zone routing. Built on the completion layer. Ignore it if you do not need it.