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

pi-other-provider

v0.3.1

Published

Unofficial custom pi providers: OpenCode Zen/Go (protocol-routing fix) + Command Code + Factory Droid (session adapter)

Downloads

222

Readme

pi-other-provider

pi-extension

⚠️ UNOFFICIAL. This is a community package. It is not affiliated with, endorsed by, or maintained by OpenCode, Command Code, Factory, or the pi core team.

Custom model providers for pi that fix protocol-routing bugs in the built-in opencode / opencode-go providers, vendor the Command Code provider, and add a session-based Factory Droid adapter — all in one package.

Why this exists

pi-ai ships built-in opencode and opencode-go providers, but several models are routed to the wrong wire protocol, causing 400 errors:

| Model | Tier | Built-in routes to | Correct route | | ------------ | ---- | ------------------------------- | ------------- | | Qwen3.x | Go | /chat/completions (rejected!) | /messages | | MiniMax M2.7 | Go | /chat/completions (rejected!) | /messages | | MiniMax M3 | Go | /chat/completions (rejected!) | /messages |

This package registers new provider IDs (oc-zen, oc-go) — it does not clobber the built-ins — with a data-driven routing table that pins each model to the protocol its upstream actually accepts. It also injects 5 onPayload hooks that patch known upstream incompatibilities, and vendors the full Command Code provider so both model sources work from one package.

Features

  • oc-zen / oc-go — corrected OpenCode Zen + Go (see docs/OPENCODE-BACKEND.md)
  • commandcode — vendored Command Code provider, hardened with upstream knowledge from OmniRoute (see docs/COMMANDCODE-BACKEND.md)
  • factory-droid — session-based agent adapter for Factory Droid (the API is NOT OpenAI-compatible; see docs/FACTORYDROID-BACKEND.md)
  • Live model discovery — catalogs refresh from the upstream /models endpoint through pi's own model-store cache (refreshModels hook) — new models appear without code updates
  • Usage-aware pricing — cache-hit (cacheRead / cacheWrite) rates included for cost display; Command Code requests use a stable threadId per conversation so upstream prefix caching can hit across turns (see docs/CACHING.md)
  • /providers command + on/off visibility — an interactive TUI (/providers) to turn the four providers and their individual models on/off in /model; see Model visibility below
  • Zero runtime dependenciespi-ai / pi-coding-agent / pi-tui are optional peers

Installation

# Local development (from this directory)
npx pi install .

# Or from npm (once published)
npx pi install npm:pi-other-provider

Restart/reload pi, then run /model to pick a model. Opening /model also triggers the live catalog refresh (see Caching).

Providers

| Provider | Backend | Base URL | Models | | --------------- | ------------- | ------------------------------- | -------------------- | | oc-zen | OpenCode Zen | https://opencode.ai/zen/v1 | 43 static · ~64 live | | oc-go | OpenCode Go | https://opencode.ai/zen/go/v1 | 44 static · ~48 live | | commandcode | Command Code | https://api.commandcode.ai | live fetch (52+) | | factory-droid | Factory Droid | https://api.factory.ai | 18 static |

Static counts are the curated baselines; the live counts are what the upstream /models endpoints return at refresh time (they grow over time).

The factory-droid provider is different from the others: Factory Droid is an agentic coding assistant, not a raw LLM endpoint. When pi sends a message, the Droid runs its own full agent loop (its own tools) on a Factory computer and returns the final text. pi's tools are ignored; each pi turn is one Factory agent turn. See docs/FACTORYDROID-BACKEND.md before using it.

Authentication

OpenCode (Zen + Go — one key for both)

  1. Environment variable (recommended):

    export OPENCODE_API_KEY="your-key"
  2. Auth file — entries are keyed by provider id, so add one per custom provider (or reuse the built-in opencode-go key by copying it):

    {
    	"oc-zen": { "type": "api_key", "key": "user_..." },
    	"oc-go": { "type": "api_key", "key": "user_..." }
    }

    If the key is missing (no env var, no auth entry), the provider will not appear in /model and pi reports Could not refresh <provider> when the model selector tries to refresh its catalog.

Command Code

  1. Run /login, select Use a subscriptionCommand Code (browser flow), or
  2. Set COMMANDCODE_API_KEY, or
  3. Place the key in one of:
    • ~/.commandcode/auth.json{ "apiKey": "user_..." }
    • ~/.pi/agent/auth.json{ "commandcode": { "type": "api_key", "key": "user_..." } }

Factory Droid

Factory Droid requires a Factory computer (a session cannot run without one). It is auto-created from a cloud template when none exists; see docs/FACTORYDROID-BACKEND.md for the full lifecycle.

  1. API key — create one at https://app.factory.ai/settings/api-keys (keys start with fk-), then either:

    export FACTORY_API_KEY="fk-your-api-key"

    or place it in ~/.factory/settings.json as { "apiKey": "fk-..." }.

  2. Computer id (recommended) — set FACTORY_DROID_COMPUTER_ID to an existing Factory computer for stability; otherwise the provider reuses an active e2b computer or auto-creates one.

Environment variables

| Variable | Provider | Purpose | | ----------------------------------- | ------------- | ---------------------------------------------------- | | OPENCODE_API_KEY | oc-zen/oc-go | OpenCode key (shared by both tiers) | | COMMANDCODE_API_KEY | commandcode | Command Code key | | COMMANDCODE_API_BASE | commandcode | Override API base (tests/mocks) | | COMMANDCODE_MODELS_URL | commandcode | Override model catalog URL | | COMMANDCODE_MODELS_CACHE | commandcode | Override model cache file path | | COMMANDCODE_AUTH_TIMEOUT_MS | commandcode | Browser-login callback timeout (default 15s) | | FACTORY_API_KEY | factory-droid | Factory API key (fk-…, required) | | FACTORY_DROID_COMPUTER_ID | factory-droid | Reuse a specific Factory computer (recommended) | | FACTORY_DROID_MACHINE_TEMPLATE_ID | factory-droid | Template to auto-create a computer from | | FACTORY_DROID_BASE | factory-droid | Override API base (default https://api.factory.ai) | | PI_OTHER_PROVIDER_CONFIG | all | Override the visibility config file path | | PI_OTHER_PROVIDER_DISABLE | all | Comma list of provider ids to disable (* = all) |

Model visibility (on/off in /model)

You control which of the four providers registered by this packageoc-zen, oc-go, commandcode, factory-droid — show up in pi's /model selector (and in /login). This only affects these providers; every other pi provider is left alone.

There are two layers. Both are optional — by default everything is visible.

1. Provider on/off

Disable a whole provider so it is not registered at all (it then disappears from both /model and /login):

// ~/.pi/agent/pi-other-provider.json
{
	"oc-go": { "enabled": false },
}

Or, faster, with an env var (no file needed):

# Disable oc-go and commandcode:
export PI_OTHER_PROVIDER_DISABLE=oc-go,commandcode
# Disable all three of this package's providers:
export PI_OTHER_PROVIDER_DISABLE='*'

2. Model-level filtering

Keep only some models, or hide a few, using glob patterns (* matches any run of characters):

// ~/.pi/agent/pi-other-provider.json
{
	"oc-zen": { "showOnly": ["claude*", "deepseek*"] },
	"oc-go": { "hide": ["mimo-*"] },
	"commandcode": { "showOnly": ["claude*", "qwen*"] },
}
  • showOnly — if set and non-empty, only models whose id matches at least one pattern are shown.
  • hide — models matching any pattern are hidden. Applied after showOnly.
  • Matching is case-sensitive and applies to the model id only.
  • * = any characters; e.g. claude*, *-pro, deepseek-*-low.

How it works

pi's own filterModels provider hook is only forwarded from pi-ai base providers, never from extensions, so this package controls visibility at the source: the model list it passes to registerProvider and the lists its refreshModels hook returns (which pi persists to its model-store cache). The live catalog is also filtered before it is persisted, so a refreshed /model list already respects the rules.

To pick up a config change you can either restart pi or open /model again (the refresh hook re-reads the config file each time).

/providers slash command (interactive TUI)

Instead of editing the JSON file by hand, run the built-in slash command inside pi:

/providers

It opens an interactive panel:

  • Main menu — pick a provider to toggle its models, or "Enable/disable providers", or "Done".
  • Per-provider model panel — a multi-toggle list of every model (on = visible in /model, off = hidden). Toggle with the keyboard; each change is saved immediately. Jump straight in with /providers oc-zen.
  • Provider on/off panel — enable/disable whole providers (/providers onoff).

Effects:

  • Model on/off → rewrites the hide list → reopen /model to apply.
  • Provider on/off → rewrites enabledrestart pi to apply (providers are registered at load time).

The rich SettingsList UI is used in TUI mode; in RPC mode (or if pi-tui is unavailable) it automatically falls back to ctx.ui.select dialogs, so the command always works. The command only affects these three providers.

How the routing fix works

Each OpenCode model is pinned to one of four wire protocols:

| Protocol | Endpoint path | pi-ai streamer | | ---------------------- | ------------------- | ------------------------------- | | openai-responses | /responses | streamSimpleOpenAIResponses | | anthropic-messages | /messages | streamSimpleAnthropic | | openai-completions | /chat/completions | streamSimpleOpenAICompletions | | google-generative-ai | /models/{id} | streamSimpleGoogle |

The custom streamSimple (src/backends/opencode/stream.ts) re-derives the protocol from the catalog, overrides the model's api + baseUrl, injects the gotcha hooks, and delegates to the matching pi-ai built-in streamer — so streaming, abort, usage parsing and prompt-cache hints (cache_control) keep working exactly like the built-in providers.

How pi actually reaches this streamSimple: every registered model carries api: "opencode-custom" (the OPENCODE_CUSTOM_API marker), matching the provider's api. pi's stream router only invokes an extension's streamSimple when model.api === provider.api, so the marker is what makes the gotcha hooks run — stream.ts then re-derives the real protocol from the catalog. Setting model.api to the real protocol instead would silently bypass every gotcha (a previous regression, now guarded by tests/test-stream.ts).

Gotcha hooks (onPayload)

Five transforms applied to every OpenCode request, ported from OmniRoute's OpencodeExecutor:

  1. stripClientMetadata — removes client_metadata (upstream 400 "Extra inputs not permitted")
  2. limitTools — caps tools at 128
  3. rewriteEffortTier — expands effort aliases (deepseek-v4-pro-low → base + reasoning_effort: low)
  4. stripBooleanReasoning — removes boolean reasoning fields some upstreams reject
  5. injectReasoningContent — echoes reasoning_content on assistant messages for thinking models (DeepSeek, Kimi, MiniMax, MiMo, big-pickle) — OpenAI-completions transport only

Command Code hardening

The vendored backend was aligned with OmniRoute's commandCode executor:

  • x-cli-environment: "external", x-taste-learning: "false" (privacy opt-out)
  • max_tokens is not fabricated — only forwarded when pi sets it, clamped to the 200k endpoint ceiling (avoids the 400 "Too big" rejection)
  • Passthrough of reasoning_effort / reasoning / thinking / effort / output_config / extra_body (payload-rule overrides are not dropped)
  • memory/taste/skills sent as "" (not null), plus permissionMode: "standard"
  • Stable threadId per pi conversation (from options.sessionId) so upstream prompt caching can hit across turns

Caching

Two distinct cache concepts, both supported (details: docs/CACHING.md):

  1. Model catalog cache — pi's models-store.json persists the live model list; refreshed when you open /model, restored on offline startups.
  2. Usage cache hits — provider-side prompt caching while chatting:
    • OpenCode: pi-ai streamers send cache_control / prompt-cache keys automatically; pricing tables include cacheRead/cacheWrite rates.
    • Command Code: stable threadId per conversation enables cross-turn prefix caching; cacheRead/cacheWrite tokens are parsed from responses and costed at their discounted rates.

Development

npm test            # typecheck + full unit suite (mocked HTTP, no real calls)
npm run typecheck   # tsc --noEmit

See docs/DEVELOPMENT.md for conventions and gotchas (e.g. never import @earendil-works/pi-ai/<subpath> — pi loads extensions via tsx and ESM-only subpath exports mis-resolve).

Documentation

Update / remove

npx pi update --extensions   # update installed packages
npx pi remove pi-other-provider

License

MIT