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

v1.2.2

Published

StarRouter is a focused model-routing extension for Pi. It chooses the best available model and thinking level for each prompt using a deterministic heuristic prompt profiler, Artificial Analysis benchmark data, provider-scoped model pools, strict model i

Readme

StarRouter for Pi

StarRouter 1.2.2 is a local, deterministic model-routing extension for Pi. Before a turn, it profiles the prompt, compares benchmark-backed candidates inside one configured provider, and chooses a model plus supported thinking level. It asks for confirmation by default and can abstain when evidence is weak.

Version 1.2.0 added redacted in-memory decision traces, benchmark attribution, /router explain, and explicit offline replay. Version 1.2.2 makes one intentional, bounded profiler-policy correction: a general-only lexical fallback is now presented as unclassified with limited evidence, keeps an eligible current route, and otherwise abstains. Internal tier IDs and replay schema version one remain readable and the 80 golden prompt expectations stay unchanged; a pre-1.2.2 general-only replay may correctly report the intentional policy delta.

There is no remote classifier and no cross-provider fallback. Artificial Analysis data supplies model measurements; prompt text is never sent there.

Requirements and installation

  • Node.js >=22.19.0
  • Pi >=0.82.1 (verified with 0.82.1)
pi install npm:pi-star-router

Then reload Pi and opt in:

/reload
/router settings
/router on

For a one-off run:

pi -e npm:pi-star-router

Routing is off by default.

Command surface

| Command | Behavior | | --- | --- | | /router status | Reports enabled/disabled state and, when enabled, the latest decision. | | /router explain | Formats the latest in-memory decision or routing-attempt trace without exposing the raw prompt. | | /router replay export [bundle.json] | Explicitly exports the latest replay capture to a private, bounded JSON bundle. | | /router replay verify <bundle.json> | Re-runs the frozen deterministic route kernel offline and reports route/ranking/score deltas. | | /router on | Enables routing for subsequent turns in the active session branch. | | /router off | Disables routing and removes the ambient decision widget. | | /router refresh | Forces an Artificial Analysis dataset refresh. | | /router settings | Opens transactional settings in TUI mode. |

Runtime pipeline

  1. Local prompt profile. English/Italian dictionaries and structural signals detect mechanical transforms, simple output, coding, debugging, architecture, security, research, agentic/tool work, structured output, long context, and vision. Mixed intents are additive: formatting language cannot erase a debugging or security signal. If no task family is recognized, the profile is uncertain and publicly labeled unclassified · limited evidence; absence of a signal is not treated as proof of simplicity.
  2. Task requirements. The profile sets benchmark weights, context/vision needs, cost and speed sensitivity, a compatible internal routing tier, and a provisional target thinking level. Public surfaces describe detected evidence rather than claiming objective task difficulty.
  3. Provider scope. Only currently available text models from strategy.routingProvider are eligible. An unavailable configured provider produces no silent fallback to another provider.
  4. Candidate generation. Provider filters are applied, then candidates are created only for thinking variants supported by Pi/model metadata.
  5. Identity match. A Pi model may borrow an Artificial Analysis row only after vendor, family/subfamily, generation/version, moving-alias, and reasoning-class checks. Host-compatible rows are host-verified. Because AA may not benchmark an aggregator itself, a small explicit allowlist (including OpenRouter) may use an otherwise identity-compatible row as model-only; this never relaxes identity gates.
  6. Normalization and ranking. Qualified host/deployment identity is preserved, and true duplicates select one coherent source row rather than combining the best field from each row. Host-verified evidence can contribute AA price, output speed, latency, and context fallback. Token burn is retained as diagnostic evidence but does not affect ranking. Model-only evidence contributes benchmark/model quality only; economics/context must come from Pi metadata and host performance is unavailable. Latency uses end-to-end evidence pool-wide when any candidate has it; TTFT is used only when the entire pool lacks end-to-end measurements. balanced ranks by composite; quality, cheapest, and fastest rank lexicographically by their named primary metric with deterministic tie-breakers. Cheapest/fastest abstain when their primary evidence is absent.
  7. Safety gates. Vision, context capacity, task thinking floors/caps, minimum AA identity match, and a relative quality floor are hard constraints. Standard weak Pareto filtering removes routes that are no better on any observed dimension. Low overall confidence causes abstention unless a trustworthy current route can be kept. General-only limited evidence follows the same conservative outcome directly and never enters simple-efficiency routing.
  8. Hysteresis. The current route is retained when its objective score is within preferCurrentWithin of the winner, reducing model flapping.
  9. Confirmation and explanation. Auto-accept is off by default. Decisions keep the deterministic recommendation and its basis separate from the applied route and its origin, so a manual alternative cannot be reported as the algorithmic winner. A compact widget records both identities when they differ.
  10. Observability without authority. The 1.2.0 layer records a bounded, redacted trace only after the deterministic kernel has decided. Ranking and benchmark attribution share one numerical implementation; detailed attribution is materialized only for the top three candidates. Trace assembly, formatting, or replay-capture failure cannot invalidate an already applied route.

See docs/algorithm.md for the ranking invariants and limitations.

Route confirmation and runtime modes

TUI

The confirmation overlay focuses the current recommendation. Controls are:

↑ / ↓   move focus
Enter   confirm the focused route
Esc     cancel and keep the current route

There is no separate Space-to-mark step. The layout degrades to a compact view on small terminals. The decision widget above the editor is capped at four lines.

RPC

Route confirmation uses Pi's serializable ctx.ui.select() surface. Decision widgets are plain text lines rather than TUI component factories, so RPC clients receive useful rationale.

Print/headless

/router status, /router explain, and replay results print plain text. Transactional settings require TUI and direct users to edit JSON otherwise. If confirmation is required but no interactive UI exists, StarRouter conservatively keeps the current route. Set global ui.autoAcceptRouting only when unattended switching is intentional.

Explainability and offline replay

After a routing attempt, inspect the latest activity with:

/router explain

Successful decisions include the redacted profile, provider scope, recommendation basis, application origin, selected and runner-up routes, benchmark coverage, per-metric contributions, missing metrics, and score breakdown. Skipped attempts explain outcomes such as exact follow-up retention, empty input, insufficient prompt-profile evidence, unavailable data, or no trustworthy route. The new insufficient-profile outcome is an additive, bounded in-memory V1 attempt record; it is neither persisted nor exported. The profile line shows an evidence-qualified label, detected score, provisional thinking target, and uncertainty state. TUI, RPC, and print modes consume the same plain-text formatter.

Traces are memory-only diagnostics. They contain prompt character count, image presence, and derived profile evidence, but no raw prompt, prompt hash, image content, conversation content, response, or credential. They are cleared when the active session branch is restored or changed and are not added to Pi session entries.

Replay export is separate and always explicit:

/router replay export                         # private default path
/router replay export ./decision.json         # explicit cwd-relative path
/router replay verify ./decision.json         # no network or profiler rerun

The default directory is ~/.pi/agent/extensions/star-router/replays/. A replay freezes the derived profile, route-relevant strategy, model registry snapshot, validated AA snapshot, expected route, ranking, and scores. Verification re-runs only the current deterministic route kernel; it deliberately does not re-profile the original prompt or emulate the old implementation. Therefore a valid pre-1.2.2 general-only V1 bundle remains readable but can report the intentional conservative-policy delta. JSON is schema-versioned, bounded to 16 MiB, structurally validated, work-limited, and written atomically with file mode 0600; newly created parent directories request mode 0700 on supported Unix filesystems. Its SHA-256 value detects accidental or adversarial input mutation but is not a signature and does not establish provenance. Treat replay files as potentially sensitive model/configuration metadata even though prompt text and secrets are excluded.

Transactional settings and filters

Open /router settings in TUI mode. All edits stay in an in-memory draft until:

Ctrl+S   save the selected global or project draft
Esc      cancel without writing

Switching the save target keeps independent global and project drafts. In project scope, global-only controls are visibly inherited and read-only.

The model-filter screen is also transactional:

Enter          toggle the focused family/model
Ctrl+S         apply the filter draft to the settings draft
Esc            cancel filter edits
Ctrl+Shift+S   save a named preset without applying the draft

Built-in presets (benchmark-safe, frontier-safe, coding-safe, budget-safe) are templates, not locks. Configuration and saved-preset reads are byte/count/string bounded; malformed, oversized, or prototype-sensitive project JSON is ignored rather than merged.

Configuration and trust boundary

Configuration is loaded from:

  • global: ~/.pi/agent/model-router.json
  • project: .pi/model-router.json

model-router.json.example is a complete global example. It includes privileged controls and data-source settings. model-router.project.json.example contains only project-safe fields.

Global configuration can control

  • enabled
  • strategy.routingProvider
  • ui.autoAcceptRouting
  • all dataSource fields, including endpoint and optional API-key environment variable
  • all project-safe fields below

Project configuration can control only

  • strategy.objective
  • strategy.qualityFloor
  • strategy.preferCurrentWithin
  • strategy.minAaMatch
  • strategy.minRouteConfidence
  • ui.showAdvancedSettings
  • filters
  • modelOverrides

Project attempts to set enabled, strategy.routingProvider, ui.autoAcceptRouting, or dataSource are ignored. This prevents a checked-out repository from enabling routing, changing providers, auto-accepting switches, redirecting benchmark traffic, or selecting secret headers.

Dataset, network, and cache behavior

StarRouter's only core network dependency is benchmark metadata:

  1. it requests the configured Artificial Analysis API path;
  2. if API parsing/fetching fails, it can parse the configured Artificial Analysis page fallback;
  3. a validated cache is stored atomically at ~/.pi/agent/cache/star-router-public.json;
  4. a fresh validated cache is preferred, and a stale validated cache may be used if both network paths fail; failure to persist an already validated network snapshot is non-fatal for the current run;
  5. /router refresh bypasses a fresh disk cache and reports whether it reached the network or retained a validated stale fallback;
  6. responses, caches, model/profile counts, and external strings are bounded and validated before routing;
  7. unknown optional AA prompt buckets are ignored while recognized routing profiles remain strict;
  8. if no trustworthy dataset is available, routing is skipped and the current route is kept.

Fetches are single-flight and bounded by requestTimeoutMs. Dataset/cache rows are validated before use, and obsolete generations cannot overwrite a newer cache. Qualified host labels such as Google (AI Studio), Google (Vertex), and DeepInfra (Turbo) remain distinct. Deployment grouping includes hostApiId, but that field can never certify host economics; host proof uses exact normalized hostLabel/hostSlug aliases. A direct-provider host mismatch is rejected. For the explicit aggregator allowlist only, a hosted mismatch becomes degraded model-only evidence: AA host price/speed/E2E/TTFT/token-burn/context fallback are suppressed, confidence is reduced, and rationale says so. Unhosted page-scrape rows use the same model-only scope. Secret headers are attached only to the official https://artificialanalysis.ai origin; a custom global endpoint does not receive them.

Artificial Analysis is an external source whose page/API schema and measurements may change. /router refresh is therefore an operational refresh, not a guarantee that every provider model will match.

Privacy and persisted state

  • Prompt profiling runs locally and deterministically.
  • No prompt text, images, Pi conversation content, provider tokens, or model responses are sent to Artificial Analysis.
  • There are zero classifier-model calls.
  • Session entries persist only enabled state and compact route-decision summaries; recommendation basis and application origin are separate, and cancellation persists a null clear marker so an old widget is not resurrected.
  • 1.2.0 decision/attempt traces remain in memory only. Replay files exist only after /router replay export, exclude raw prompts and prompt hashes, and can reveal route, model, benchmark, and safe strategy metadata.
  • The public dataset cache contains benchmark/model metadata, not prompts.
  • StarRouter reads provider availability/auth status from Pi but does not log or persist provider secrets.

See SECURITY.md for the full trust model and reporting path.

Reproducible validation

The default suite is deliberately offline. Its preload denies Fetch/WebSocket and the standard in-process Node HTTP(S), HTTP/2, TCP, TLS, UDP, and DNS entry points unless a test replaces fetch() with a local deterministic stub. This is a regression guard, not an operating-system sandbox: it intentionally does not claim to contain malicious child processes or native code.

npm test                 # alias for test:offline
npm run test:offline     # 155 deterministic offline tests
npm run golden           # 80/80 checked-in golden prompts
npm run typecheck
npm run smoke
npm run perf:check        # offline replay/trace p95 budgets
npm audit --omit=dev --audit-level=low  # shipped StarRouter surface
npm pack --dry-run --json

The 1.2.2 release gate targets 155 offline tests, 80/80 golden prompts, nine unchanged replay fixtures, strict TypeScript, release smoke checks, offline observability performance budgets, production-surface audit, package-content inspection, and Pi 0.82.1 compatibility CI. Version 1.2.2 intentionally changes only general-only uncertainty policy and public task-profile wording; recognized prompt families retain the prior routing semantics.

As of 2026-08-06, the production/--omit=dev surface audit reports zero vulnerabilities. The full development-tree audit reports three upstream findings inherited through the npm-shrinkwrapped Pi 0.82.1 tooling: one moderate and two high, involving undici advisories plus brace-expansion. They are not shipped in the StarRouter tarball; the extension does not call brace-expansion, and the affected undici copy belongs to the local/CI Pi CLI dependency. Pi 0.82.1 resolves the earlier nested protobufjs advisory. The remaining tooling risk is documented rather than hidden by a lockfile-only substitution; updating Pi is intentionally outside this patch.

perf:check executes 180 network-disabled observations across the nine replay fixtures and enforces conservative defaults of 75 ms replay-verify p95 and 5 ms trace validate/format p95. On the 2026-07-27 Pi 0.82.1 release workstation it observed 0.918 ms and 0.269 ms respectively. A same-process paired kernel benchmark for the 1.2.1 release tree executed 47,250 routes per implementation against baseline 3c4c147: median chooseRoute time was 0.0475 ms at baseline and 0.0509 ms for 1.2.1 (+0.0034 ms, +7.2%). Detailed top-three attribution is deliberately populated after chooseRoute, so observability failure cannot suppress a valid route. These values are machine-specific release evidence, not universal latency promises.

Live OpenRouter catalog observations are opt-in and are not a PR gate:

npm run test:live        # 8 tests, one shared request per external source/file
npm run test:all         # offline first, then live

The live suite makes two external requests (one shared OpenRouter request and one shared Artificial Analysis request) to check current catalog/schema shape, representative IDs, parseable prices, and model-only aggregator compatibility. It intentionally makes no universal savings claim. To evaluate cost for your workload, record the observation timestamp, exact provider/model IDs, input/output/cache token counts, provider fees, and the baseline selection policy; then rerun the comparison when catalog prices change.

Troubleshooting

Router status → disabled

Run /router on, or save enabled: true in the global file. Project config cannot enable routing.

Configured provider shows unavailable

Authenticate/configure that provider in Pi or change the global routing provider. StarRouter will not borrow another provider silently.

No trustworthy route

The provider may have no benchmarkable available model, an identity/host gate may reject the match, or confidence may be below the configured floor. Keep the current route, inspect filters/overrides, and run /router refresh.

Dataset refresh fails

Check connectivity, the configured timeout, and the Artificial Analysis endpoint. A validated stale cache is used when available; otherwise routing abstains.

Settings unavailable in RPC/print

Edit the appropriate JSON file. Keep privileged fields in the global file.

A model name does not match AA

Add a narrow modelOverrides slug pin after verifying creator, exact version, evidence scope, and reasoning class. The pin resolves alias naming only; contradictory or missing fixed identity evidence is still rejected. A versioned moving alias can be pinned explicitly, with reduced confidence. For aggregator model-only evidence, AA host economics remain suppressed even when pinned.

Repository map

index.ts                            Pi lifecycle, commands, runtime routing
src/router-core.ts                  config trust boundary, AA ingestion, ranking
src/decision-trace.ts               versioned redacted trace and attribution contracts
src/route-replay.ts                 explicit bounded replay export and offline verification
src/prompt-understanding.ts         deterministic EN/IT prompt profiler
src/route-choice-screen.ts          responsive confirmation and widgets
src/settings-screen.ts              transactional settings UI
src/model-filters-screen.ts         transactional provider/model filters
src/filter-presets/                 built-in and saved presets
docs/algorithm.md                   algorithm invariants and limitations
docs/index.html                     self-contained public project page
tests/*.test.ts                     deterministic offline release suite
tests/fixtures/replays/             frozen route/ranking/score replay corpus
tests/live/*.live.test.ts           explicit network observations
model-router.json.example           complete global example
model-router.project.json.example   project-safe example

Release notes and license

See CHANGELOG.md for the 1.2.2 low-evidence correction, the 1.2.1 Pi baseline update, the 1.2.0 observability release, and earlier migration notes. Licensed under MIT.