DeepSeek Harness 插件

dsh-key-rotation

Per-provider API key rotation for DeepSeek Harness: a key pool per provider, auto-created clone routes, and switching to the next key on quota/rate-limit errors. Includes a Settings section (Key(英文原文)

跳到安装方式

来源信息

GitHub 仓库
GooDAnDReaDY/dsh-key-rotation
最近更新
2026年8月19日
分类
模型与服务商
GitHub stars
0
载体类型
plugin
目录证据
上游声明已找到 dsh.bundle
证据路径
package.json#dsh.bundle
核对版本
0.1.0-rc.8
上游核对日期
2026-08-20

该证据由上游目录提供。本站没有安装、运行或安全审核这个插件。

安装

默认先复制一段 Prompt,让 Agent 读 GitHub 仓库和源码;需要自己装时再切到命令。

复制这段 Prompt,发给 DSH、Codex 或其他 Agent,让它先读 GitHub 仓库和源码。

请先不要安装或执行任何命令。阅读这个插件的 GitHub 仓库、README 和关键源码,然后用清楚、直接的方式回答以下问题,帮助我判断它是否适合我的需求:

1. 这个插件是什么,解决什么问题;
2. 适合哪些用户和典型使用场景;
3. 安装后如何使用,并给出一个最小使用示例;
4. 有哪些已知限制,以及隐私、安全、兼容性或维护风险;
5. 给出“推荐 / 有条件推荐 / 不推荐”的明确建议和理由。

请区分仓库明确说明、根据源码推断和未知信息。证据不足时请明确说明,不要猜测或照抄 README。

GitHub:https://github.com/GooDAnDReaDY/dsh-key-rotation
插件名:dsh-key-rotation
作者:GooDAnDReaDY

检查来源文件

安装前先看这个插件目录里的 README 和其他文件。

文件资源管理器3 个文件
README.md来源说明 · 只读预览

dsh-key-rotation

Per-provider API key rotation for DeepSeek Harness (dsh). Instead of failing on a quota/rate-limit error, the plugin transparently retries the request on the next healthy key in a per-provider pool.

> Hermes-style rotation: every configured provider has a key pool; when a key's limit is exhausted, the request is retried on the next key. Exhausted keys stay in cooldown and return to rotation after cooldownMs.

What it does

  • Key pools per provider — list the API keys (as credential/env names) that a provider may rotate through.
  • The provider you picked stays the provider — rotation swaps the key, never the route, so a multi-call turn does not break. Legacy clone routes remain registered but are hidden from the model dropdown.
  • Transparent on-failure rotation — on a switchable error (QUOTA, RATE_LIMIT, AUTH/INVALID…) the request is retried on the next key.
  • Cooldown — an exhausted key is skipped for cooldownMs, then returns.
  • Dead/revoked key handling — an auth/invalid key rotates to the next pool key instead of erroring out.
  • Settings GUI — a Settings → Key Rotation section to manage everything without touching config files:

- add a key in one place — press Add key, paste the value, done. The credential name is generated for you (<PROVIDER>_API_KEY, then _2, _3, …) and shown only on hover; the card lists keys as Key 1, Key 2. - live key status — per key: in use / ready / cooling down with a countdown / no such credential, which is what catches a mistyped name that would otherwise fail silently. - rotation counter — how many times a provider switched key, on which failure, and how long ago. - key order — ↑/↓ buttons; the order of keys is the order they are tried. - switch codes as checkboxes instead of a comma-separated string.

Install

# From npm after publishing:
dsh plugin --profile web add @goodandready/dsh-key-rotation

# From GitHub:
dsh plugin --profile web add github:GooDAnDReaDY/dsh-key-rotation

# Locally from a checkout:
dsh plugin --profile web add /path/to/dsh-key-rotation

Restart the Web UI afterwards.

Configure

Web GUI (recommended)

Open Settings → Key Rotation and, for each provider, list the credential names of its keys. The plugin stores this in the dsh-key-rotation settings namespace (same place as settings.yaml).

settings.yaml

dsh-key-rotation:
  switchCodes: [QUOTA, RATE_LIMIT, SERVER, TIMEOUT, TRANSPORT, EMPTY_RESPONSE, UNKNOWN_MODEL]
  cooldownMs: 60000
  providers:
    # `provider` is the id of a provider registered with dsh, as it appears
    # in Settings -> Models. `keys` are CREDENTIAL NAMES, never key values.
    - provider: my-provider
      keys: [MY_PROVIDER_API_KEY, MY_PROVIDER_API_KEY_2, MY_PROVIDER_API_KEY_3]
    - provider: another-provider
      keys: [ANOTHER_PROVIDER_API_KEY, ANOTHER_PROVIDER_API_KEY_2]
FieldDefaultDescription
switchCodes[QUOTA, RATE_LIMIT, SERVER, TIMEOUT, TRANSPORT, EMPTY_RESPONSE, UNKNOWN_MODEL]Error codes that trigger a key switch.
cooldownMs60000How long an exhausted key stays out of rotation.
providers[{ provider, keys: [envName, ...] }]. keys are credential/env names, not the key values themselves.

How keys are stored

The plugin config only ever references keys by name (e.g. MY_PROVIDER_API_KEY). The values live in the dsh Credentials service or $DSH_HOME/.credentials.yaml — never in the plugin config.

A key typed into the Key Rotation card is written to that same credentials store: the value travels to the host once and is never sent back to the browser. Only its last 5 characters are, so two keys can be told apart in the UI. A key supplied by the launching environment is shown as read-only, because overwriting it here would be shadowed anyway.

How it works

request ──► {provider: rotation} clone route ──► pick next healthy key in pool
        ┌────────┐   on switchable failure retry with next key, stay in cooldown
        └─────────┘
  • The plugin patches ctx.credentials.resolve so a pool reference resolves to the current healthy key (round-robin, skipping keys in cooldown).
  • It intercepts llm/stream to retry the request on the next key after a switchable failure, instead of surfacing the error to the caller. The hook is deliberately not async: the loop iterates its result directly, and returning a promise breaks every turn.
  • The provider identity never changes — only the resolved key does — which keeps the adapter's replay state consistent across a multi-call turn.

Two local-only routes back the card: GET /dsh-key-rotation/status (key state, rotation counters, last 5 characters of each key) and PUT|DELETE /dsh-key-rotation/key (store or drop one key value). Both refuse anything that is not a same-origin request from loopback.

Structure

dsh-key-rotation/
├── package.json            # dsh bundle/plugin metadata + peerDependencies
├── cordis.patch.yml        # bundle layer: registers the virtual route "rotation"
├── lib/index.js            # host: pools, credentials.resolve patch, stream retry
├── lib/client.js           # browser: Settings → Key Rotation panel
└── README.md

Security notes

  • Key values never leave your Credentials store; the plugin config only holds env/credential names.
  • switchCodes are error classification strings, not expressions — no secrets involved.

License

MIT