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-model-replacements

v0.3.1

Published

Model alias/tier (low/medium/high) replacement extension for pi coding agent

Readme

pi-model-replacements

hero

A standalone pi extension that lets agents, subagents, and prompt templates reference abstract model tiers (low / medium / high, or any alias name) instead of hard-coding provider/model-id. A single change in settings.json re-points every template and subagent.

How it works

Add a model_replacements map to the active agent dir's settings.json (the dir selected by PI_CODING_AGENT_DIR, e.g. ~/.pi/agent/settings.json):

{
  "model_replacements": {
    "low": "github-copilot/claude-haiku-4.5",
    "medium": "github-copilot/claude-sonnet-4.6",
    "high": "github-copilot/claude-opus-4.8"
  }
}

Now any model: low in a prompt-template frontmatter, an agent definition, or a subagent tool call resolves to the concrete model — no file writes, no edits to other extensions.

Mechanism

  1. session_start — each alias is injected into the live model registry as a synthetic model cloned from its concrete target (grouped per provider, idempotent across /reload). Unresolvable targets warn once and are skipped.
  2. model_select + initial swap — when an alias becomes the active model, it is swapped to the concrete Model object via pi.setModel. Self-terminating (the target is never an alias key, so no loop).
  3. tool_call — an explicit subagent model: "high" argument is rewritten in place to the concrete provider/model-id before the child process spawns.
  4. before_agent_start — a per-turn safety net that swaps any still-active alias immediately before the API call (covers the agent-frontmatter path and child startup ordering). The same extension code runs fresh inside subagent child processes.

Configuration resolution

PI_CODING_AGENT_DIR is honoured exactly like pi-subagents: ~ / ~/... are expanded; otherwise the literal value is used; default is ~/.pi/agent. Reading is fail-soft — a missing or malformed settings.json, or absent model_replacements, yields no aliases (extension is a no-op).

Installation

Install via pi:

pi install npm:pi-model-replacements

Development

Setup

npm install

Testing

npm test   # tsx --test *.test.ts

Works well with

Contracts and limitations

Thinking-suffix handling

pi-model-replacements resolves aliases by exact key match. A suffixed string such as "high:thinking" does not match alias key "high" directly, so the tool_call handler splits the trailing :thinking suffix, resolves the base alias ("high") to its concrete target, and re-attaches the suffix — producing e.g. "github-copilot/claude-opus-4.8:thinking".

This is required because pi-subagents' resolveModelCandidate() only matches the base model id against the live registry. Since pi-model-replacements injects each alias as a synthetic registry entry, passing "high:thinking" through unresolved would make pi-subagents select the synthetic alias id ("github-copilot/high"), which is not a real API model and fails with 400 model not supported. The alias must therefore be resolved to its concrete target here, before the child spawns.

This behaviour is locked by a regression test in tool-call.test.ts ("subagent tool_call: suffixed alias ('high:thinking') resolves base alias and re-attaches suffix").

Unsupported: alias chaining

A configuration like { "low": "medium", "medium": "provider/model" } — where an alias target is itself another alias key — is not supported. buildAliasMap detects chained entries at map-build time, emits a console.warn, and skips them. Only direct alias → "provider/model-id" mappings are accepted.

Code note: getAgentDir() duplication

alias-resolver.ts:getAgentDir() is a character-for-character copy of pi-subagents/src/shared/utils.ts:getAgentDir(). Both are intentionally kept separate to avoid cross-package coupling. Any future change to path-expansion logic (e.g., Windows normalisation) must be applied to both files.


Made with ♥ by fractiunate