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-tier-router

v0.3.1

Published

Pi extension that routes each session between a cheap flash model and a strong pro model based on issue difficulty - Claude Code style haiku/sonnet/opus tiering, config-driven for any model family.

Readme

pi-tier-router

npm repo size License: MIT Pi extension

Pay for difficulty, not for every message. Routine work runs on the cheap model; only genuinely hard issues escalate to the strong one.

Project page: rioliu.github.io/pi-tier-router

Route a Pi coding session between a cheap flash model and a strong pro model, based on how hard the issue actually is.

This is the same tiering idea as Claude Code's haiku/sonnet/opus model levels — most work belongs on the fast, inexpensive model, and a minority of hard issues deserves the strong one. Unlike a fixed tier list, the two roles are configuration: point it at any model family (MiMo, DeepSeek, an OpenAI-compatible endpoint, or a mix of providers).

What it does

Pi exposes the router as a virtual model, router/auto. While it is selected, every prompt is decided on its own the moment it arrives, and that decision serves the whole agent run (tool loop included):

prompt arrives (before_agent_start)
  0. local router reads the prompt: 0 ms, no tokens, deterministic
       clear signals  -> decided right away (flash or pro)
       mixed/missing  -> abstain
  1. on abstain: the decision store is consulted first
       a similar past verdict is reused (signal-profile overlap or trigram
       match, k-NN vote) -> no model call at all
  2. otherwise: flash model rates the issue itself (rating + confidence)
       confidence >= 0.8  -> decision is final, nothing else is consulted
       and the verdict is stored for future prompts
  3. unsure  -> ask Jev, but only if a credentialed classifier model is available
                (TYPESAFE_API_KEY, or any other Jev-capable provider in Pi's registry)
  4. no Jev  -> keep the flash model's lean
  5. neither -> keep the current model (flash for a new session); routing stops
  • One prompt, one decision — the next prompt re-decides, so a hard task can escalate without locking the whole session to pro.
  • Local first: routine and obviously hard prompts never reach a model. /auto-router status reports how often the local layer decided on its own. Signals cover English and Chinese (stack traces are language-neutral), and the scan looks at the first 32 KB only — a 1 MB paste still decides in ~0.3 ms, and past the window the layer abstains rather than guess.
  • It remembers: chain verdicts from the abstain zone are stored next to the extension — a JSONL journal on disk and a fixed typed-array ring in memory (2 000 entries, ~285 KB, never grows with age). Similar prompts reuse them instead of paying for a rating call; neighbours that disagree keep abstaining. The file is removed together with the extension, and deleting it by hand is always safe — the store rebuilds itself.
  • Jev is optional, never a dependency — consulted only when the local layer abstains and the flash model is unsure.
  • Compaction summaries always run on the flash model.
  • The model-based decision is bounded at 10s and uses minimal reasoning, so it never holds up a turn.

Install

pi install npm:pi-tier-router

Or straight from GitHub while the npm package is pending:

pi install git:github.com/rioliu/pi-tier-router

Install one or the other. Loading both silently breaks the wizard: /auto-router stops dispatching and the literal text is sent to the model instead.

Then select it: /model → router/auto, and press Ctrl+S to make it the default for new sessions. Or set it directly in settings.json:

{ "defaultProvider": "router", "defaultModel": "auto" }

Routing only runs while router/auto is selected. With any other model — including a physical pro model as your default — the extension does nothing.

Configure

The extension owns its config, next to the extension file — so uninstalling the extension takes its config with it:

<install-dir>/extensions/auto-router.json

| install method | config path | |---|---| | plain file | ~/.pi/agent/extensions/auto-router.json | | pi install npm: | ~/.pi/agent/npm/node_modules/pi-tier-router/extensions/auto-router.json | | pi install git: | ~/.pi/agent/git/github.com/rioliu/pi-tier-router/extensions/auto-router.json |

pi update preserves the file — verified for both npm and git sources. If an older copy is sitting in ~/.pi/agent/extensions/, it is read and moved next to the extension the first time it loads, so uninstalling leaves nothing behind.

{
  "flash-model": "deepseek/deepseek-v4-flash",
  "pro-model":   "deepseek/deepseek-v4-pro"
}

Values are provider/model-id (split on the first slash, so ids containing slashes work, e.g. openrouter/typesafe/jev-1.13). The two roles may live on different providers. Omitted or malformed keys fall back to a MiMo pair.

Create or change it with the built-in wizard:

| command | effect | |---|---| | /auto-router | interactive: pick both roles from the models Pi can reach | | /auto-router status | show config path, both roles, whether the pair resolves, current default | | /auto-router memory | show the decision store: path, size, ring fill, session reuse, recent verdicts | | /auto-router memory reset | wipe the store — it rebuilds itself from new verdicts | | /auto-router set flash=<provider/id> pro=<provider/id> | write the config and reload |

The wizard writes only its own file. models.json is never touched — availability is read from Pi's live model registry — and the only value read from settings.json is your default model id, used to warn you when it changes.

Behaviour when configuration changes

The extension re-checks at session start and before every prompt, so it follows your model settings instead of going silently dead:

| condition | result | |---|---| | default model is router/auto but the pair is missing | error notification + degraded (never a crash) | | configured pair missing (provider rewritten, pro model removed) | warning + router disabled | | default model changed during the run | info notification (pick it in /model to route) | | no config yet, or no matching pair | inactive; Pi behaves exactly as if it were not installed |

Issues are announced when they appear, not on every prompt.

Watching a decision

AUTO_ROUTER_DEBUG=1 pi
[auto-router] roles flash=... pro=...
[auto-router] local pro conf=0.93 via concurrency

Local decisions print a single line and cost nothing. Only an abstain reaches the store or the model chain:

[auto-router] local abstain; flash rating chain decides
[auto-router] self rated=pro conf=0.92
[auto-router] decided self/pro in 1432ms
[auto-router] stored pro by self (4 entries)

[auto-router] local abstain; flash rating chain decides
[auto-router] memory flash (3 neighbours, 100% agree)      <- no rating call at all

The interactive footer shows the routed model (auto • medium → deepseek-v4-pro) and /session lists cost per physical model.

Disable it

Pick any physical model in /model, or set your default to the pro model — routing then never engages. Removing the config file deactivates the router entirely.

Requirements

Both role models must be registered in models.json with working credentials.

The Jev step is optional: it needs a credentialed classifier model in Pi's registry (TYPESAFE_API_KEY for typesafe/jev-latest, or another Jev-capable provider). Without one, the chain simply keeps the flash model's lean — routing never depends on Jev.

Development

npm test        # node >= 23 (native TypeScript stripping)

The suite covers the local router's signal table, the decision chain, the hook → route() wiring, the decision store (round-trip through the journal, torn lines, ring and journal caps, the agreement gate), config persistence and refresh, change warnings, and the provider/model-id parser. It runs against a temporary copy of the extension, so it never writes into your real Pi directory.

References

The routing logic in this extension is built on the papers below, selected from the Awesome-Routing-LLMs survey — each one directly shapes a layer of the local -> flash rating -> Jev chain. The full analysis is in docs/local-router-research.md.

Local feature routing (layer 0)

  1. I. Ong, A. Almahairi, V. Wu, et al., "RouteLLM: Learning to Route LLMs with Preference Data," ICLR 2024. arXiv:2406.18665
  2. C. Tran, S. Paracha, A. Hafeez, S. Chen, "Arch-Router: Aligning LLM Routing with Human Preferences," ArXiv 2025. arXiv:2506.16655
  3. S. N. Hari, M. Thomson, "Tryage: Real-time, Intelligent Routing of User Prompts to Large Language Models," ArXiv 2023. arXiv:2308.11601

Confidence-gated two-tier escalation (flash self-rating, abstain band)

  1. G. Ramírez, A. Birch, I. Titov, "Optimising Calls to Large Language Models with Uncertainty-Based Two-Tier Selection," COLM 2024. arXiv:2405.02134
  2. Y.-N. Chuang et al., "Confident or Seek Stronger: Exploring Uncertainty-Based On-Device LLM Routing from Benchmarking to Generalization," NeurIPS 2025 Workshop. arXiv:2502.04428
  3. P. Aggarwal et al., "AutoMix: Automatically Mixing Language Models," NeurIPS 2024. arXiv:2310.12963

Memory-based routing (decision store, kNN reuse)

  1. Y. Li, "Rethinking Predictive Modeling for LLM Routing: When Simple kNN Beats Complex Learned Routers," ArXiv 2025. arXiv:2505.12601
  2. Z. Zhao, S. Jin, Z. M. Mao, "Eagle: Efficient Training-Free Router for Multi-LLM Inference," NeurIPS 2024 Workshop. arXiv:2409.15518

Benchmarks (coverage/risk measurement)

  1. Q. J. Hu et al., "RouterBench: A Benchmark for Multi-LLM Routing System," ICML 2024 Workshop. arXiv:2403.12031
  2. Z. Huang et al., "RouterEval: A Comprehensive Benchmark for Routing LLMs to Explore Model-level Scaling Up in LLMs," EMNLP 2025. arXiv:2503.10657

License

MIT