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

@argszero/cordis-plugin-credential-rotate

v0.1.1

Published

Per-route API-key rotation + retry for dsh. When a provider request ends with a retryable failure (default: QUOTA, AUTH — the codes where waiting cannot help), this plugin (1) repoints the provider's credential reference (e.g. llm-deepseek's apiKeyEnv) to

Readme

@argszero/cordis-plugin-credential-rotate

Per-route API-key rotation + retry for dsh — when one credential is exhausted, the next one takes the same request. No proxy, no baseURL surgery.

Grounded in discussion #6344 (“one provider route, several credentials, rotate automatically”).

What it does

A route carries one credential reference (apiKeyEnv for llm-deepseek, profile.apiKeyEnv for llm-pi-ai). When that key hits its quota or is revoked, the whole route goes dark even though the operator holds several keys.

This plugin keeps the route alive:

  1. a request fails with a rotation-eligible code (QUOTA, AUTH by default),
  2. and nothing visible has been rendered yet,
  3. so it repoints the credential reference to the next name in your pool — via settings.update(namespace, patch) — and re-runs the same request through the llm/stream waterfall. The adapter re-resolves its credential once per stream call, so the retry simply carries the next key.

When the pool is spent, the request fails visibly with code CREDENTIAL_ROTATE_EXHAUSTED (the message names every reference tried and repeats the provider's own failure text).

Install

dsh plugin --profile web add @argszero/cordis-plugin-credential-rotate

Then put the pool in the environment (values, not references — the plugin never sees them) and point the plugin at the pod that holds the reference:

DEEPSEEK_KEY_A=sk-... DEEPSEEK_KEY_B=sk-... dsh web
# profile layer
- set:
    - id: credential-rotate
      config:
        pods: ['llm-deepseek:apiKeyEnv']
        refs: [DEEPSEEK_KEY_A, DEEPSEEK_KEY_B]

refs are environment-variable names. A reference that resolves to nothing is skipped with a warning — it is never installed as an empty key.

| option | default | meaning | |---|---|---| | pods | [] | <settingsNamespace>:<field> addresses that hold the credential reference | | refs | (required) | the pool, tried in order | | rotateCodes | [QUOTA, AUTH] | failure codes that justify a rotation | | maxRotationsPerRequest | 3 | rotations allowed inside one request | | maxPodWritesPerRotation | 200 | write bound for one rotation move |

Why not rotate on RATE_LIMIT too?

RATE_LIMIT is transient — the same key usually works again after the provider's own Retry-After, which the in-tree llm-retry policy already honours. QUOTA and AUTH are the codes where waiting cannot help. Rotating on RATE_LIMIT would burn every key on one throttled minute; if you disagree, add it to rotateCodes explicitly.

What it deliberately does not do

  • No response buffering. Chunks are forwarded the instant they arrive. The only withheld data is the head of an attempt (chunks that arrived before anything visible), which must not be replayed if that attempt is discarded. That buffer closes permanently at the first visible delta.
  • No rotation after visible output. A mid-stream failure is passed through untouched: re-running a partially-rendered answer would duplicate it, and that policy belongs to the harness (assistant/attempt), not to a plugin.
  • No unbounded retry. Rotations are bounded by maxRotationsPerRequest and the pool length; the failure always surfaces.
  • No durability. The pool cursor is per-request, so a restart re-starts the pool from the top while the installed reference survives in settings. Rotation is a latency optimization, not a quota accountant.

Compatibility

dsh 0.1.2-rc.1, 0.1.3-alpha.2, 0.1.5, and 0.1.6 (>=0.1.2-rc.1 <0.1.3 || >=0.1.3-alpha.2 <0.1.4 || >=0.1.5-alpha.1 <0.2.0 || >=0.1.6-alpha.1 <0.2.0). The wrapped seam (llm/stream) and the per-stream-call credential resolution both predate this range; every line above has had the full suite run against it.

License

MIT