@kushalkhemka/pi-openrouter

Provider-pinned OpenRouter models and exact cost, cache, TPS, and subagent accounting for Pi.

Packages

Package details

extension

Install @kushalkhemka/pi-openrouter from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@kushalkhemka/pi-openrouter
Package
@kushalkhemka/pi-openrouter
Version
1.0.7
Published
Sep 5, 2026
Downloads
877/mo · 877/wk
Author
kushalkhemka
License
MIT
Types
extension
Size
49.9 KB
Dependencies
0 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-openrouter

Provider-pinned OpenRouter models and trustworthy usage accounting for the Pi coding agent.

Instead of choosing model-id and letting OpenRouter select an endpoint, this extension adds selector entries shaped like:

deepseek/deepseek-v4-flash-0731:deepinfra/fp8

The suffix is OpenRouter's exact endpoint tag. Every request made through that entry sends provider.only with that tag and allow_fallbacks: false, so it cannot silently move to another provider.

Install

pi install npm:@kushalkhemka/pi-openrouter

Authenticate with Pi's normal OpenRouter login, then restart Pi:

/login openrouter
/model

No API key is stored by this package. It reuses Pi's OpenRouter authentication.

The extension intentionally overrides Pi's built-in openrouter model catalog under the same provider ID. Pi keeps its native OpenRouter login and streaming implementation; only the model list is replaced with exact endpoint-pinned entries.

Pi loads the cached catalog immediately and schedules a live refresh after startup. If an agent starts while that refresh is running, the refresh is cancelled and retried after the agent settles, so catalog traffic does not compete with model traffic.

What it does

  • Downloads OpenRouter's live model catalog and exact endpoint list.
  • Includes healthy endpoints that support tools, which are suitable for coding-agent use.
  • Replaces OpenRouter's unpinned selector entries with model-id:endpoint-tag entries.
  • Uses endpoint-specific context limits, output limits, modalities, reasoning support, and prices.
  • Uses OpenRouter's per-model supported_efforts metadata so Pi exposes only valid thinking levels, including xhigh and max when available.
  • Loads the public catalog from a local cache without blocking startup, then refreshes it automatically while Pi is idle. /openrouter-refresh remains available for an immediate manual refresh.
  • Reconciles completed generations with OpenRouter's generation API for actual cost, actual provider, native completion tokens, and server-reported generation time.
  • Calculates cache-hit rate as cache read / (new input + cache read + cache write).
  • Calculates TPS as native completion tokens divided by OpenRouter generation time. When reconciliation is unavailable, it reports a labelled streaming estimate.
  • Tracks assistant calls inside sessions spawned by @tintinweb/pi-subagents, including nested child sessions when extensions remain enabled.
  • Listens for subagents:started, subagents:completed, subagents:failed, and subagents:compacted. The lifecycle-reported usage is used only as a fallback when no child message was observed, avoiding double counting.
  • Stores numeric metrics only—never prompts, responses, request headers, or API keys.
  • Keeps request rewriting synchronous and in-memory, performs metrics file writes asynchronously, and reconciles completed generations on a lightweight interval outside active provider requests.
  • Detects when the package is loaded twice in one Pi session, disables the duplicate handlers, and leaves separate subagent sessions active.

Commands

/openrouter-stats             current Pi session, including observed subagents
/openrouter-stats subagents   current subagent usage only
/openrouter-stats all         persisted history
/openrouter-status            catalog/accounting diagnostics
/openrouter-refresh           refresh endpoints and prices now

The footer also shows the running cost, weighted cache-hit rate, and weighted TPS for the current session.

Metric definitions

  • Cost: OpenRouter total_cost when its generation record is available; otherwise Pi's endpoint-price estimate.
  • Weighted cache hit: total cache-read tokens divided by total prompt-side tokens. This is more representative than averaging percentages from a tiny and a huge request.
  • Average/request cache hit: arithmetic mean of each request's cache-hit percentage, shown separately.
  • Weighted TPS: output tokens divided by summed generation seconds. Exact records use OpenRouter native output tokens and generation time.
  • Subagent cost: direct child-session generations are included in the overall total and separately subtotalled. Pi-subagents' terminal aggregate is a fallback, not an additional charge.

Metrics are append-only JSONL at ~/.pi/agent/pi-openrouter/metrics.jsonl; the latest row for a generation ID wins after reconciliation. The public catalog cache is ~/.pi/agent/pi-openrouter/catalog.json.

Environment

PI_OPENROUTER_DATA_DIR changes the catalog and metrics directory, useful for isolated testing.

PI_OPENROUTER_METRICS_INTERVAL_MS changes the reconciliation interval. The default is 3000 ms; values are clamped between 1000 and 60000 ms.

Development

npm install
npm run check

Security

Selecting an exact provider makes routing predictable, but the selected provider still receives the request. Review that provider's data policy and OpenRouter routing/privacy settings for sensitive code. See SECURITY.md.

License

MIT