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

@alma-harness/providers

v0.12.0

Published

ModelClient adapters for Anthropic and OpenAI over Alma's neutral message format.

Readme

@alma-harness/providers

ModelClient adapters for Alma: Anthropic and OpenAI first-party, plus the OpenRouter gateway bridge, over one neutral message format.

Status: pre-1.0. The API is still moving; see the roadmap for where it stands.

What it owns

  • AnthropicModelClient — Messages API, streaming, with explicit cache_control breakpoints (at the wire's default duration, or the hour a policy asks for — spec: cache-ttl; the other two wires refuse the ask) at the stable-system boundary and the conversation tail.
  • OpenAIModelClient — Responses API, streaming, automatic prefix caching.
  • OpenRouterModelClient — the gateway bridge (chat completions). A gateway does not answer "who processed this data?" by itself, so construction REQUIRES a declared upstream allowlist, fallbacks are off by default, data collection is denied by default, and require_parameters rides along whenever the request carries tools. Opening the catalogue changes nothing about what the routing policy permits — that stays a product/DPO decision.
  • The translation between Alma's neutral Msg/Block format and each provider's wire format, in both directions.

Routing decides which client runs; the adapter only speaks the protocol.

import { OpenRouterModelClient } from "@alma-harness/providers";

const client = new OpenRouterModelClient({
  upstreams: ["deepinfra", "together"], // the declared data-processing chain
});

Credentials

The harness never owns credentials. Each client accepts an explicitly injected key or falls back to the SDK's own environment resolution — configuration comes from the hosting environment, never from a file this repo reads.

import { AnthropicModelClient } from "@alma-harness/providers";

const client = new AnthropicModelClient();          // reads ANTHROPIC_API_KEY
const explicit = new AnthropicModelClient({ apiKey }); // or inject it

Jobs

AnthropicJobClient (Message Batches) and OpenAIJobClient (the Batch API, over a JSONL file of /v1/responses requests) implement the ModelJobClient seam (spec: model-jobs): the same request translations, minus streaming, and a non-streaming translation of the complete answer. OpenRouter has no batch API.

Reasoning

When the policy sets ModelChoice.reasoning (spec: reasoning-blocks), each adapter asks for it and hands it back as one complete block per step:

| effort | Anthropic | OpenAI | OpenRouter | |---|---|---|---| | absent | nothing sent; default output dropped | nothing sent; default items dropped | nothing sent | | none | thinking: disabled | reasoning.effort: none | reasoning.enabled: false | | others | thinking: adaptive + output_config.effort | reasoning.effort + encrypted content | reasoning.effort |

An adapter replays only its own blocks, and only when reasoning is on for the request; every other reasoning block in the history is skipped.

Provider-executed web search

ModelRequest.providerTools (spec: provider-tools) declares the provider's own search beside the registered tools; what comes back is two neutral blocks, provider_tool_call and provider_tool_result, the provider's payload kept opaque for replay.

| | Anthropic | OpenAI | OpenRouter | |---|---|---|---| | declaration | web_search_20250305 (the direct search; the agentic 2026-03-18 version drives code_execution and is another kind) with max_uses, allowed_domains, blocked_domains | { type: "web_search", filters: { allowed_domains } } + include: ["web_search_call.action.sources"]; blockedDomains is REFUSED before the network; maxUses is the loop's to enforce | refused before the network | | on the stream | server_tool_use → call; web_search_tool_result → result (url, title, page age; an error code as error); usage.server_tool_use.web_search_requests | a completed web_search_call item → call (input: action) and result (the sources; failed as an error), counted | — | | replay | its own two blocks as server_tool_use + web_search_tool_result with the encrypted content, only while the request declares the kind (a capped step replays the text and skips the search); another provider's skipped | its own result's opaque as the item, only while the request declares the kind; the call block skipped | skipped | | pause_turn | → the neutral pause: the loop re-sends | — | — |

Media

| | Anthropic | OpenAI | OpenRouter | |---|---|---|---| | image by URL | source: { type: "url" } | input_image with the URL | image_url with the URL | | image by bytes (spec: media-by-bytes) | base64 source; JPEG, PNG, GIF, WebP, else refused | input_image with a data URL | image_url with a data URL | | document | by URL: document source · by bytes: base64 PDF, else refused | by bytes only: input_file with a data URL and the ref's filename, PDF · by URL refused | refused | | audio | refused — products transcribe upstream | refused | refused |

A block carries bytes when the loop attached content from the product's MediaSource; the adapters never fetch anything and never see the ref's path on the bytes path.

Structured output and cache controls

ModelRequest.output selects native JSON schema output (spec: provider-request-controls). It introduces no tool or business handler. Responses still arrive as text and usage/stop events: validate the result and inspect refusal/truncation before treating it as application data. The governed single-call runner is not part of this slice.

| Control | Anthropic | OpenAI | OpenRouter | |---|---|---|---| | output: {type: "json_schema", name, schema} | output_config.format with type/schema, preserving reasoning effort | text.format with strict: true | refused | | format name | validated portable label; no wire slot, intentionally omitted | required wire name | refused | | cache: false | removes both explicit breakpoints | refused | refused | | cache: {ttl, conversationTail: false} | only the last stable system block gets a breakpoint | refused | refused | | absent controls | existing defaults | existing defaults | existing defaults |

Names use 1–64 ASCII letters, digits, underscores or dashes. Schemas must be objects and comply with the selected provider's strict schema subset; arbitrary tool input schemas are not automatically converted. Model-specific schema support is validated by the provider. Cache controls preserve message roles and order; disabling the tail prevents a system suffix from being included in that breakpoint. Disabling prompt cache is not a data-retention or erasure setting.

Streaming and batch reuse these mappings (toAnthropicBatchRequests and toBatchLines expose the pure batch translations). Unsupported options reject before network activity, including batch file upload. These fixtures prove serialization against installed SDK types, not live model acceptance.

Arguments the wire cut

A tool call whose arguments do not parse — a response cut by max_tokens mid-arguments, or a model that emitted broken JSON — is still a tool_call (spec: what-the-wire-cuts): input: {} and the raw text as malformed, followed by the wire's own stop reason. The loop answers a malformed call with an invalid-input result on tool_use, and closes it on max_tokens. The translators never throw on it.

Errors

What an SDK throws leaves every client as a ProviderError from @alma-harness/core (spec: error-taxonomy), classified through one duck-typed table over the fields the SDKs share: 429 → rate_limited (OpenAI's insufficient_quotarejected); 529, 503 or an overloaded body → overloaded; no status or 5xx → unavailable; a 400 that says the prompt does not fit → context_window; the other 4xx → rejected. A user abort passes through untouched. The translation error classes are ProviderErrors too — rejected before the network, provider_drift mid-stream — and toProviderError / classifyFailure are exported for a product wrapping its own client.

What it must never do

  • Decide routing, spend, or capability. Those are core, not adapter.
  • Leak a provider type into the neutral format — the format is the boundary that makes a second provider cheap.
  • Swallow provider drift: a stream that ends without a stop event fails loudly rather than looking like a successful empty turn.

Documentation

Docs index · Architecture §6.2 · Anthropic adapter spec · OpenAI adapter spec

Apache-2.0

Opt-in single-dispatch clients

createAnthropicSingleDispatchClient({ apiKey?, baseURL? }) and createOpenAISingleDispatchClient({ apiKey?, baseURL? }) return a frozen SingleDispatchModelClient. They disable SDK retries and HTTP redirects and withhold authentication-provider, middleware and transport injection options. The existing constructors keep their current retry/usage behavior; batches and OpenRouter do not implement this new capability.

The capability accepts the same neutral tools, tool results, supported media and reasoning history as the first-party translators, plus supported system, JSON schema, reasoning, tier and cache controls (spec: rich-single-dispatch-requests). It executes no local tool handler; the host owns authorization and sensitivity. validate is pure and streamEvidence validates/clones before its first network await. These checks prove local adapter support, not model-specific schema acceptance. Clone errors are content-free rejected ProviderErrors. Consume each returned stream once.

Known final counts are emitted before stop or a terminal translation error. Missing/invalid/partial usage never becomes zero. unpriced preserves counts for unknown served tiers or missing/mixed/inconsistent cache TTL attribution, and must not be sent to pricing with a fallback. Anthropic final cumulative updates win; OpenAI input excludes cache reads AND writes to avoid counting writes twice. OpenAI search counts use unique completed item identities and terminal output when present; missing/conflicting attribution remains unknown. Anthropic search activity requires a valid positive cumulative search count. Known and unpriced evidence retain search counts without copying queries or URLs into billing metadata. Only bounded provider request IDs enter reference events, including HTTP errors. Content events remain content: never store the whole evidence stream as a financial row. OpenAI still sends store: false.

The legacy stream method on these new clients converts known evidence to a usage event and fails on unknown/unpriced evidence. Drain streamEvidence to retain known usage even if a later error occurs. Pre-abort is not-dispatched; all ambiguous network outcomes require reconciliation. An early return aborts transport even immediately after headers, but cannot promise final usage. This is transport evidence, not durable deduplication or invoice reconciliation.

Reasoning history replays through the existing translator when reasoning is enabled and the block belongs to that provider. Preserve opaque replay content unchanged. This support does not itself adopt durable multi-turn execution. Reusing a stream fails with a rejected ProviderError. Caller cancellation preserves the AbortSignal reason, including custom errors.

Explicit temperature

temperature is optional and sent unchanged in streaming and batch bodies. The matrix admits Anthropic 1, plus 0..1 for claude-haiku-4-5 and claude-haiku-4-5-20251001 with reasoning absent or none (spec: haiku-temperature-compatibility), and OpenAI GPT-5.1/GPT-5.2 base IDs or dated snapshots with explicit reasoning none, in 0..2. Pro/chat/codex variants and OpenRouter reject it. This is a conservative adapter matrix; other Anthropic IDs remain explicit-1-only. Omit it for provider defaults. Invalid/unsupported values fail before network or batch upload; zero is preserved. There is no automatic downgrade or determinism guarantee.

Single-dispatch batch evidence

createAnthropicSingleDispatchBatchClient and createOpenAISingleDispatchBatchClient implement execution's additive SingleDispatchBatchClient. Frozen capabilities admit apiKey/baseURL only, with SDK retries disabled and redirects rejected. Legacy job clients are unchanged. Validate 1..512 unique batch-tier items (IDs: ASCII alphanumeric, underscore or hyphen, max64), one model, and a 16 MiB wire bound before network. Requests and handles are snapshotted before asynchronous work. Use a trusted immutable configuration for baseURL/account selection.

Consume submitEvidence exactly once after a durable dispatch:true decision. OpenAI yields input_file before its separate create POST, then accepted. Save needed file evidence before resuming. Lost responses never authorize another attempt; creating a new iterable is a new attempt. File cleanup is not provided. Resolve handles and expected item IDs from the scoped durable manifest before polling or collecting: the adapter itself provides no tenant authorization.

resultsEvidence requires terminal status and yields independently validated usage and content, including when translation fails. Cancellation in progress remains running. Both OpenAI result files are read, even for terminal cancellation. Anthropic result URLs must match the configured origin and batch results path before authenticated retrieval. JSONL is incremental, with a 2 MiB line/32 MiB collection limit, max512 expected IDs, and readers cancelled on abandonment. Unknown, duplicate or missing IDs fail the collection. Prior observations survive such failure and must not be interpreted as complete collection or free remainder.

Batch transport supplies batch billing for compatible default tier fields; contradictory tiers and mixed cache TTLs remain unpriced. Missing counts stay unknown. Content has no duplicate usage field; provider errors have closed reasons. Server-tool content may be unusable while its validated search charges survive. These are adapter prerequisites, not durable collection or settlement. No runner, routine, production delivery or live billing validation is implied.

Governed OpenRouter requests

createOpenRouterSingleDispatchClient({ upstreams: ['anthropic'], apiKey }) implements the same SingleDispatchModelClient capability as the first-party factories. It snapshots the declared upstream list, denies data collection by default, and disables gateway fallbacks, SDK retries and HTTP redirects. Optional zeroDataRetention and explicit dataCollection retain the gateway translator's controls. allowFallbacks: true is rejected; the legacy constructor remains unchanged until cutover. The key defaults only from OPENROUTER_API_KEY.

The adapter preserves the current text/tool/image/reasoning translator and its unsupported-control refusals. Financial evidence uses native token counts from the final usage chunk: ordinary input excludes cache reads and writes, and reasoning is a subset of output. Positive cache writes without a TTL are unpriced; missing or malformed counts are unknown. A context-window HTTP error never proves zero usage. Candidate counts stay private until the stream closes or fails; contradictory observed chunks fail without an early known charge. The provider's cost field does not replace the runner's persisted price table. The promise is one Alma inference attempt, with gateway fallback disabled, not an attestation of the gateway's internal infrastructure. See spec openrouter-single-dispatch.

The Anthropic single-dispatch adapter attests anthropic_context_window_v1 only for the exact structured HTTP 400 input-window rejection before SSE, with a bounded request ID and known zero usage. Generic errors and post-stream failures remain uncertain. OpenAI/OpenRouter do not attest this proof. No automatic SDK retry is added; the governed conversation owns any continuation after settlement (spec: safe-context-rejection-rotation).

Both official single-dispatch batch clients support cancel(handle, {signal?}) (spec: governed-batch-cancellation-adoption). Each explicit invocation sends at most one cancellation POST, with SDK retries and redirects disabled. Handles are snapshotted before awaiting; returned identity, status and counts are validated. Anthropic canceling and OpenAI cancelling remain running. Lost acknowledgements and malformed responses reject without another request or invented terminal state.

Explicit client-tool selection

ModelRequest.toolChoice is optional host policy (spec: governed-tool-choice). Absence sends no tool_choice and retains previous provider behavior; explicit auto remains distinct from absence in execution identity. No choice grants permission to a tool or runs its handler.

| Neutral control | Anthropic streaming / batch | OpenAI Responses / batch | OpenRouter | |---|---|---|---| | { type: "auto" } | { type: "auto" } | "auto" | refused | | { type: "none" } | { type: "none" } | "none" | refused | | { type: "required" } | { type: "any" } | "required" | refused | | { type: "tool", name } | { type: "tool", name } | { type: "function", name } | refused |

Forced modes (required / tool) admit these exact IDs only:

  • Anthropic: claude-haiku-4-5, claude-haiku-4-5-20251001, claude-sonnet-4-5, claude-sonnet-4-5-20250929, claude-sonnet-4-6, claude-opus-4-5, claude-opus-4-5-20251101, claude-opus-4-6, claude-opus-4-7.
  • OpenAI: gpt-4.1, gpt-4.1-mini, gpt-5.1, gpt-5.2, gpt-5.6-luna, gpt-6-sol, gpt-6-luna.

Other IDs, including unlisted dated snapshots, reject forcing before network. Auto/none use the documented first-party wire without a forced-model allowlist; model availability and general model capabilities remain provider concerns. All explicit choices reject simultaneous output or nonempty providerTools. Forced modes on other models reject an explicit reasoning effort other than none. For exact OpenAI gpt-5.6-luna, use explicit reasoning none/low/medium/high/xhigh/max in both execution controls and the loaded request (spec: luna-forced-reasoning). Omitted, minimal, unknown and malformed efforts reject; no provider default is silently selected. Active efforts retain the existing summary and encrypted reasoning transport for stateless replay in Responses and batch. Reasoning tokens are already part of output tokens and are not charged again. Auto/none and omitted selection retain existing behavior. Omit temperature; Luna temperature support is unchanged. The remaining conservative model/provider guards are retained rather than extrapolated from Luna compatibility. No control is silently downgraded, and absence bypasses this new matrix.

A named tool must match exactly one advertised ToolSpec; forced modes need client tools. Invalid shapes, names and ambiguous registries reject before stream dispatch or batch file upload. The single-dispatch clients snapshot requests before asynchronous work; all first-party batch mappings share the stream translator. OpenRouter explicit selection is refused until a reviewed model/upstream matrix can guarantee local validation.

For a governed structured one-call result, use createGovernedStepRunner from @alma-harness/single-call with the same choice in planned execution controls and its loaded request. Inspect the tool calls, original stop and receipts; a forced choice does not guarantee valid arguments, a successful stop or exactly one block. The text/JSON createSingleCallRunner does not accept this control. See the single-call composition. There is no automatic tool execution or personal-memory write on the structured step path.

Sources checked 2026-09-17: Anthropic tool selection, Anthropic thinking compatibility, OpenAI function calling, Luna capabilities and default effort, OpenAI batch body parity, OpenRouter tool calling. Deterministic tests establish serialization, rejection and governed composition. A maintainer-authorized synthetic named-tool probe on 2026-09-17 succeeded with medium and xhigh; the latter returned nonzero reasoning usage. This is not a quality evaluation, live batch proof or consumer integration claim.

GPT-6 Sol and Luna

Exact gpt-6-sol and gpt-6-luna support Responses streaming, governed single calls and per-item batch translation. Forced tools require explicit none|low|medium|high|xhigh|max reasoning. Unsupported efforts reject before HTTP even without forced selection. Without forcing, omitted reasoning preserves the provider default. Temperature and simultaneous output/forced-tool guards remain unchanged. No application model default is switched automatically.

These two models send system blocks as ordered developer input text, with an explicit breakpoint at the end of the initial consecutive stable prefix and prompt_cache_options: {mode: "implicit", ttl: "30m"}. The provider selects the conversation breakpoint. Keep instructions/tools/history stable and place changing content after the stable prefix. A stable block following volatile content does not receive a breakpoint. Existing model request shapes remain unchanged.

OpenAI requires at least 1,024 visible input tokens for cache eligibility; no hit or latency reduction is guaranteed. Cache writes cost 1.25 times ordinary input, reads 0.1 times, and each reuse renews the minimum 30-minute lifetime. The adapter subtracts both counts from ordinary input on legacy and governed paths, so writes are not billed twice. Reasoning remains included in output. fast is normalized to neutral priority; a contradictory tier in governed batch remains unpriced.

The existing cache field expresses Anthropic 5m/1h TTL controls. OpenAI still rejects explicit values, including false; this release adds automatic prefix placement, not a new public cache-policy contract. Prewarming, cache keys, explicit-only mode and mid-conversation reasoning changes are not exposed. store:false remains set; it does not disable provider KV caching or promise zero cache retention. Confirm organizational data-retention requirements.

Host price table

Prices remain host-owned and versioned. Populate both cache rates rather than relying on core's ordinary-input fallback. Standard USD per million tokens, checked 2026-09-22:

| Model | Input | Cache read | Cache write | Output | |---|---:|---:|---:|---:| | gpt-6-sol | 2 | 0.20 | 2.50 | 10 | | gpt-6-luna | 0.10 | 0.01 | 0.125 | 0.50 |

For each tier row, add bands: [{aboveInputTokens: 272_000, ...rates}] with input/read/write rates doubled and output multiplied by 1.5. The threshold uses ordinary input plus reads plus writes and applies to the whole request. Flex/batch multiply all standard rates by 0.5; priority/Fast by 2. Regional processing adds 10% where applicable; EU residency supports Standard only. These token prices do not cover separately billed provider tools.

const model = { provider: "openai" as const, id: "gpt-6-luna" };
const prices = [{
  model, inputUsdPerMTok: 0.10, outputUsdPerMTok: 0.50,
  cacheReadUsdPerMTok: 0.01, cacheWriteUsdPerMTok: 0.125,
  bands: [{ aboveInputTokens: 272_000, inputUsdPerMTok: 0.20,
    outputUsdPerMTok: 0.75, cacheReadUsdPerMTok: 0.02,
    cacheWriteUsdPerMTok: 0.25 }],
}];

Sources: Sol, Luna, prompt caching, Fast mode. Synthetic fixtures verify translation, accounting and installed governed replay; no live cache-hit, model-quality or batch-acceptance claim is implied.