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

@pugi/plugin-anvil-provider

v0.1.0-alpha.2

Published

Pugi Anvil provider plugin - multi-tenant routing for Pugi via AI-SDK OpenAI-compatible adapter.

Downloads

283

Readme

@pugi/plugin-anvil-provider

Pugi Anvil provider plugin: multi-tenant routing for the soft-forked Pugi core via the AI-SDK OpenAI-compatible adapter.

Part of the Pugi 1.0 soft fork sprint (see ADR-0081).

What it does

Registers the Pugi Anvil gateway (https://anvil.pugi.io/v1) as a first-class provider inside Pugi and pipes every chat call through it with tenant-scoping headers. A single Pugi process can serve many Pugi tenants because the bearer token is hashed into a stable tenant_<hex> id that is never logged or stored raw.

Anvil owns the server-side provider fallback chain (Together AI Qwen3-Coder-480B by default per CEO directive 2026-06-05, then OpenRouter free tier, Cerebras, Groq) so the plugin stays small: it sets the headers, validates the response, and surfaces typed errors.

Hook surface

| Hook | Purpose | |---|---| | config | Register Config.provider['anvil'] with the AI-SDK npm adapter, baseURL, bearer, and static model catalog. Primes the tier cache once at startup. | | provider | Dynamic model listing via GET /v1/models; falls back to the static catalog when the gateway is unreachable. | | chat.headers | Inject X-Pugi-Tenant, X-Pugi-Plugin-Version, X-Pugi-Session, X-Pugi-Provider-Fallback, X-Pugi-Tier, and X-Pugi-Upgrade-Hint on every chat call. |

Install

pnpm add @pugi/plugin-anvil-provider
pnpm add @ai-sdk/openai-compatible    # peer

Usage

// pugi.config.ts
export default {
  plugin: [
    [
      '@pugi/plugin-anvil-provider',
      {
        apiKey: process.env.PUGI_API_KEY,
        anvilBase: 'https://anvil.pugi.io/v1',
        // tenantId is derived from sha256(apiKey) if omitted.
        // resolveSession is called per request so trace ids stitch in Langfuse.
        resolveSession: async () => process.env.PUGI_SESSION_ID,
      },
    ],
  ],
};

Options

| Option | Default | Notes | |---|---|---| | apiKey | process.env.PUGI_API_KEY | Required for production use. Used as bearer plus tenant derivation seed. | | anvilBase | https://anvil.pugi.io/v1 | Trailing slash is normalised away. | | tenantId | tenant_<sha256(apiKey)[:32]> | Override to pin a specific tenant id (multi-process deployments). | | providerId | anvil | Key under Config.provider and id in the model picker. | | tenantHeader | X-Pugi-Tenant | Override only when running against a non-default Anvil deployment. | | fallbackChain | ['anvil-primary', 'openrouter-free', 'cerebras', 'groq'] | Sent as X-Pugi-Provider-Fallback. Anvil enforces server-side. | | tierCachePath | ~/.pugi/anvil-tier.json | Filesystem path for the tier snapshot. Override for tests. | | tierCacheTtlMs | 3600000 (1 hour) | TTL before re-fetch from GET /v1/me. | | defaultModel | qwen3-coder-480b | Default routed model id. Set to pugi-auto to let Anvil pick. | | resolveSession | () => undefined | Resolver for the active session id; threaded into X-Pugi-Session. |

Tier matrix

The GET /v1/me response is cached to disk for one hour. Each tier maps to the per-minute and per-month caps that Anvil already enforces server-side; the plugin surfaces the snapshot in the X-Pugi-Tier header so downstream observability can attribute usage.

| Tier | Per-minute rate limit | Monthly token cap | Notes | |---|---|---|---| | free | 25 | 1M | Upgrade hint surfaces in X-Pugi-Upgrade-Hint. | | founder | 50 | 10M | Pugi Founder $20/mo. | | builder | 100 | 100M | Pugi Builder $99/mo. | | team | 500 | 1B | Pugi Team $199/mo. | | enterprise | per contract | per contract | Resolved via the customer table. |

Error handling

All product errors are surfaced as a discriminated AnvilError union. Hook callers use the isAnvilError(err) type guard to narrow:

| kind | Source | Behaviour | |---|---|---| | rate_limited | HTTP 429 | retryAfterMs parsed from Retry-After header. | | upgrade_required | HTTP 402 | tier parsed from response body. Includes upgrade URL. | | upstream_unavailable | HTTP 5xx | Surfaced verbatim. Anvil already ran its fallback chain. | | unauthorized | HTTP 401 / 403 | Prompts the operator to re-run pugi login. | | network | Transport failure | Retried three times with 100 / 500 / 2000 ms backoff before throwing. |

Architecture notes

  • HTTP client is native fetch, no axios.
  • Tier cache is plain JSON on disk; no Redis dependency.
  • Effect-TS is intentionally not imported anywhere in this package, per the ADR-0081 containment rule.
  • Retry strategy is fixed delays without jitter; clients are single-tenant and request volume is low.
  • Authorization header is set via Config.provider['anvil'].options.apiKey so Pugi handles refresh and rotation; chat.headers is reserved for Pugi-specific metadata.

Tests

pnpm --filter @pugi/plugin-anvil-provider test

Twelve specs cover option resolution, the three hooks, tier caching, stale-cache replay, retry behaviour, and the 402 / 429 / 5xx response mapping. A node:http fake server is used; no real Anvil traffic is generated.

License

MIT. See LICENSE.