npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hawkeyexl/inference

v0.3.0

Published

Shared TypeScript LLM inference layer: schema-constrained completion across Anthropic, OpenAI-compatible, Claude CLI, and in-process local llama.cpp providers, with caching, cost accounting, and an LLM-as-judge ensemble.

Readme

@hawkeyexl/inference

Shared LLM inference layer for the docs-as-tests toolchain: schema-constrained completion across Anthropic, OpenAI-compatible, Claude CLI, and in-process local (llama.cpp) providers, with result caching, cost accounting, and an LLM-as-judge ensemble on top.

Extracted from three projects that had each grown their own copy — docevals, dockg, and agentevals — so a provider fix lands once instead of three times.

📖 Documentation

Install

npm install @hawkeyexl/inference

Requires Node 24+. Three runtime dependencies, plus one optional peer dependency for local models.

ESM only. The exports map has no require condition, so require("@hawkeyexl/inference") fails with ERR_PACKAGE_PATH_NOT_EXPORTED. From CommonJS, use await import("@hawkeyexl/inference").

What it does

Every consumer wants the same narrow thing: send a system prompt, a user prompt, and a JSON Schema; get back JSON that validates against that schema, or a recorded error.

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

No streaming, no multi-turn, no tool loops. If you need a conversation, this is the wrong package. Widening the provider contract requires an ADR.

Two layers, one entry point:

  • Completion — the provider contract, five providers, a content-addressed cache, a price table, and a validate-and-retry wrapper. All that structured extraction needs.
  • Judge — the 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.

Quick start

No API key required — MockProvider is exported for exactly this.

import { MockProvider, completeValidatedJSON } from "@hawkeyexl/inference";

const run = await completeValidatedJSON({
  provider: new MockProvider([{ json: { summary: "Covers authentication." } }]),
  system: "You summarize documentation pages.",
  user: pageBody,
  schema: {
    type: "object",
    required: ["summary"],
    properties: { summary: { type: "string" } },
    additionalProperties: false,
  },
});

if (run.error) console.error(run.error);
else console.log(run.result.summary, run.usage);

completeValidatedJSON never throws on a model failure and never coerces a bad response. It retries once, then returns a run with error set and result absent.

Point it at a real model by swapping the provider — or omit provider entirely and let the library detect one this machine can use, ending at the free local model:

const provider = await makeProviderAsync({});

Providers

| provider | Structured output via | Credential | Reports usage | |---|---|---|:---:| | anthropic | forced tool call | ANTHROPIC_API_KEY | yes | | openai | strict json_schema, falls back to json_object | OPENAI_API_KEY | yes | | claude-cli | schema in the prompt, --output-format json | local claude auth | no | | llama-cpp | GBNF grammar compiled from the schema | — (runs locally) | yes | | mock | scripted responses | — | synthetic |

Omit provider and the highest-priority one this machine can actually use is detected, ending at llama-cpp — which needs no key, and whose native binding is installed on demand into ~/.hawkeyexl-inference/runtime if it is missing. That install warns once and is refused by INFERENCE_NO_AUTO_INSTALL; it never touches your package.json, lockfile or node_modules.

Usage reporting is the column that decides whether cost accounting works: a provider that reports no tokens makes a budget gate inert. See Choose a provider.

Documentation

| Track | What it covers | |---|---| | Get started | Install, one validated call with no key, choosing a provider | | Judge & consensus | Ensembles, consensus math, confidence zones, caching, budgets | | Structured extraction | One schema-constrained call, honest failures, the subprocess seam | | Run models locally | GGUF weights in-process, model selection, managing weights on disk | | Keep it working | Testing without a network, upgrading without losing a cache | | Reference | Full signatures for every export |

Who the docs serve and why each page exists lives in docs/content-strategy/.

Design decisions

Recorded as ADRs in adrs/:

  • 01000 — a library-owned ProviderSpec, not consumer config objects
  • 01001 — one entry point; a canonical verdict schema with a per-consumer override seam
  • 01002 — which fork won for each merged file, so the losing variants are not reintroduced
  • 01003 — in-process local models via node-llama-cpp, why selectors need an async factory, and why the catalog pins exact blob paths
  • 01004 — detect an available provider when none is specified, ending at the local model
  • 01005 — a CUJ-first documentation set, with samples that CI executes
  • 01006 — document failure and orchestration, and gate both against the source
  • 01007 — harden two operational failure paths: non-JSON CLI output, and an unsupported Node
  • 01008 — auto-install the local runtime into a library-owned prefix, why the shim beats createRequire, and why a model without a provider is now an error

License

MIT