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

@booplex/bpx-endpoints

v0.2.0

Published

Pi extension. Manage model endpoints — discovery, metadata sources, generated config, and a Pi-native TUI — through one /endpoints command.

Readme

bpx-endpoints — every model endpoint, one command | pi extension

pi ships with presets for the big hosted providers, and that's fine until your models live somewhere pi has never heard of. A load balancer in front of your model accounts. The vLLM box under the desk. A regional gateway with its own key dance. The stock answer is hand-editing ~/.pi/agent/models.json, then hand-updating it every time the endpoint's model list changes — which is exactly the kind of chore I build tools to kill.

bpx-endpoints puts all of it behind one command: /endpoints. Point an endpoint at pi and it discovers the model list, pulls parameter metadata from pi's registry plus models.dev, generates the config, and registers the endpoint into your live session. One Pi-native overlay holds the model-by-model knobs; refresh and doctor keep it honest over time.

Works in pi (the coding agent, v0.80+).


What it's for

pi's built-in presets already cover the known providers with correct base URLs and metadata, so this extension doesn't duplicate a preset catalog. It covers everything the presets don't:

  • OpenAI-compatible proxies and load balancers
  • Self-hosted endpoints (LM Studio, Ollama, vLLM)
  • Regional gateways
  • Any deployment where you supply the base URL, protocol, and key yourself

Install

pi install npm:@booplex/bpx-endpoints

Restart your pi session and /endpoints wires itself in.

git clone https://github.com/gabelul/bpx-mono
cd bpx-mono
pi install ./packages/bpx-endpoints

Getting started

Everything runs through /endpoints. The typical first run:

  1. Run /endpoints add (or open /endpoints and press a).
  2. Fill in the endpoint form inside the Endpoint Manager. The Endpoint ID defaults to endpoint-1 and stays editable. ↑/↓ to move, Enter to edit, → on Authentication to change its mode once a value is set.
  3. Pick an API protocol from pi's runtime list, or enter a custom protocol id. Protocol is never inferred from the URL — an endpoint that speaks OpenAI-completions at an /v1 path is not the same as one that speaks OpenAI-responses, and guessing wrong fails in confusing ways.
  4. Enter the Base URL and choose authentication: None, environment variable, literal key, or shell command. None is valid for local services like LM Studio, vLLM, and llama.cpp.
  5. Choose endpoint discovery or enter exact model IDs manually. Ctrl+T tests model discovery; a /models failure doesn't mean chat is broken — it means switch to manual IDs.
  6. Save with Ctrl+S. The Endpoint Manager stays open and shows completion; model management and test messages are optional follow-ups.

Each endpoint maps to exactly one pi.registerProvider() call. Once saved, the endpoint generates into pi's config and registers live in the session — no restart needed.

Commands

/endpoints                 Open the Endpoint Manager
/endpoints add             Add an endpoint through interactive prompts
/endpoints settings        Edit extension settings (same picker as /consult)
/endpoints status          Print a config / cache / generated read-out
/endpoints list            List endpoints
/endpoints refresh         Refresh all enabled endpoints
/endpoints refresh <id>    Refresh a single endpoint
/endpoints test <id> [model]   Send a test message (streams, reports latency)
/endpoints test --all          Batch-test all enabled endpoints (one confirm)
/endpoints probe-reasoning [id]  Probe accepted reasoning_effort values
/endpoints doctor          Diagnose config / cache / generated / custom state
/endpoints export [path]   Write masked effective generated + custom config
/endpoints open            Show the config file + state directory paths

The overlay is the primary interface; the subcommands are shortcuts for scripting and recovery. Add, edit, refresh, model management, and completion all happen inside one overlay session — no dialog teardown, no flicker. It floats centered at 92% of your terminal width, so the form and model tables keep their columns on narrow screens too. From the overlay you can also check endpoint status, clone (y), delete, send an explicit test message, and reach the advanced override layer. Test messages stream through the endpoint's real protocol (the exact registered model, including models.custom.json overrides), time out after 30s, and record latency + failure history that /endpoints doctor and /endpoints status surface.

Model discovery and metadata

  • Discovery runs in two modes: endpoint discovery (discovery.mode: "endpoint" + modelsPath) or manual entry (discovery.mode: "manual" + modelIds).
  • Full URL override: discovery.modelsUrl bypasses baseUrl + path entirely — for endpoints like Ollama whose chat API lives at .../v1 but model list at http://host:11434/api/tags.
  • Path probing (discovery.probe: true): when the configured URL returns 404, an unsupported shape, or an empty list, bpx-endpoints automatically tries /models, /v1/models, /api/tags, and /api/models at the origin. Never on auth failures — 401/403 are reported, not guessed around. The resolved URL is cached per profile so later refreshes skip the guessing.
  • Response shapes accepted: bare arrays, data[], models[], data.models[] nesting, and object-keyed maps. Duplicate ids are dropped, entries without an id are skipped (both counted in warnings).
  • Bounded retries: discovery and models.dev sync retry once on transient network errors, 429 (honoring Retry-After), and 5xx.
  • Parameter sources for each model come from pi's built-in metadata plus models.dev sync, cached locally with a 24h TTL and offline fallback — refresh works without depending on a remote. Unsourced or fuzzy matches show as warnings; unsourced models fall back to built-in defaults until verified. The default source is the first sorted candidate, and you can pick another from /endpoints.
  • Inclusion policy is includeAll with exclusions by default, or includeOnly with an explicit list of model ids.
  • Per-model overrides of arbitrary fields live in modelOverrides or the custom override layer.

Reasoning efforts

Pi sends reasoning_effort = thinkingLevelMap[level] ?? level to OpenAI-compatible endpoints. A null or missing map entry makes pi leak the raw thinking level ("high", "xhigh") as the wire value — and real servers reject those: OpenAI's schema only accepts low/medium/high, and some self-hosted servers accept even less. bpx-endpoints therefore never copies a metadata source's thinkingLevelMap verbatim for openai-completions reasoning models. It always emits a complete map:

  • Unknown endpoint → canonical low/medium/high map, so no pi level can ever leak a rejected value.
  • Live probe (discovery.reasoningProbe: true) → on refresh, bpx-endpoints sends one tiny chat completion (1 token) per candidate value (low, medium, high, xhigh) and records which the endpoint accepts. Rejections are classified from the error body; because validation is eager, a probe timeout counts as accepted (the server rejected the bad values instantly and is just slow at generating). The map then picks the nearest accepted effort for every pi thinking level.
  • Manual override (reasoningEfforts: ["low", "medium"] on the profile) → wins over probe results, for endpoints where you already know the schema.
  • If the endpoint accepts no effort value, reasoning models register as non-reasoning (any reasoning_effort would 400) with a doctor warning — set compat.thinkingFormat in models.custom.json if the model thinks via a different parameter.
  • A complete thinkingLevelMap you author yourself (e.g. in models.custom.json) is never clobbered — explicit user intent wins when there's no probe/manual ground truth.

Probe results are cached per profile and surfaced in the models overlay (ctrl+r re-probes), in /endpoints probe-reasoning [id], and in doctor/status. One probe run makes up to four 1-token calls, so it's opt-in via the form's Reasoning probe field.

Custom headers

For endpoints that don't use the default Authorization: Bearer <apiKey> style, an endpoint can carry optional headers. They apply to endpoint discovery and land in the generated provider config for pi's requests. Header values support the same literal, $ENV_VAR, and !command forms as apiKey. Choose Authentication None when custom headers provide all required auth.

{
  "headers": {
    "x-api-key": "$MY_GATEWAY_KEY"
  }
}

Base URL references

baseUrl also supports value references, expanded at use time — config files keep the reference, so nothing resolved lands on disk and env changes apply on the next session:

  • $VAR and ${VAR} expand from the environment, including mid-URL: "baseUrl": "http://${MY_HOST}:8080/v1". An unset variable is a hard error at discovery/test/registration time (failing fast beats sending a broken URL to DNS).
  • !command (whole value only) runs a shell command and uses its trimmed stdout: "baseUrl": "!~/bin/tunnel-url.sh".
  • Plain URLs pass through untouched, including $ that isn't a variable name (?price=$5).

Configuration

Managed config lives in a single flat file at ~/.pi/agent/bpx-endpoints.json (the pi-native path, beside pi's own state) — TypeBox-schema validated, fail-soft on load, crash-resistant on save. Derived state lives under ~/.pi/agent/bpx-endpoints/:

| File | Purpose | | --- | --- | | bpx-endpoints.json | Managed user intent: endpoint profiles + settings (TypeBox-validated) | | cache.json | Discovered endpoint models and metadata candidates, plus per-profile test health (last test time, latency, failure count) | | models.generated.json | Generated pi models.json-shaped config | | models.custom.json | Unrestricted override layer, merged after the generated config | | models.dev.json | Local models.dev catalog cache (24h TTL, offline fallback) |

The config directory is created 0700; extension-owned JSON files are written 0600. The extension never writes to pi's native ~/.pi/agent/models.json — that file stays yours.

Settings edit through /endpoints settings (same interactive picker as /consult) or /endpoints status for a read-out: stale reminder on/off and the stale-day threshold (default 7). Status also summarizes test health per profile (ok / failing / never tested).

On first run, existing state is migrated automatically — from bpx-endpoints/config.json if present, otherwise the legacy ~/.pi/agent/custom-provider/ directory — so existing endpoints survive the switch. The flat file is never overwritten once it exists, and a malformed legacy config is never converted into defaults.

Startup only performs the local generated/custom merge and endpoint registration; it never touches the network. Deleted, disabled, or no-longer-generated endpoints unregister from the live session immediately. Endpoint rows show cache age, and doctor plus the startup reminder flag caches older than the stale threshold (set settings.staleReminderDays in bpx-endpoints.json, or settings.staleReminder: false to silence the reminder).

Error handling

| Situation | Behavior | | --- | --- | | Missing models.generated.json | Normal onboarding; no endpoints registered | | Invalid models.generated.json | Registration skipped, but /endpoints, refresh, doctor, and recovery still work | | Invalid models.custom.json | Ignored with a warning; generated endpoints still register | | Invalid bpx-endpoints.json | Already-generated endpoints still register, but edit/refresh enter recovery until fixed; /endpoints settings refuses to open over a broken file rather than overwrite it | | Unresolved API protocol | The affected endpoint is invalid — not generated, not registered, no silent fallback |

Development

git clone https://github.com/gabelul/bpx-mono
cd bpx-mono
npm install
npm run check   # typecheck + tests, monorepo-wide

Issues and PRs at gabelul/bpx-mono.