DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Provider Rate Limit — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
P

dsh-provider-rate-limit

Provider Rate Limit

针对每个提供商和每个模型的速率限制(令牌桶、拒绝/排队模式),以及 DeepSeek Harness 的网关身份规则

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:jyao-SUSE-power-group/dsh-provider-rate-limit#3de070c3a8258b8cecffc148f125ddc466480e74
README兼容性版本
Settings CardSettings Config 1Settings Config 2Composer Dock Stats

兼容性与来源证明

Provider Rate Limit 以 dsh-provider-rate-limit 发布,当前版本为 0.3.1。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/9/6

版本

0.3.1stable
2026/9/6
0.3.0stable
2026/8/23
0.2.2stable
2026/8/23

相关插件

正在加载相关插件…

最新版
0.3.1
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 2
周下载
0
最近提交
2026/9/10
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 security-access 分类下经过校验的插件。

Doctor@linxin666/dsh-doctorDSH 配置档案的事务性救援模式,配备受监督的启动器、隔离的恢复容器、确定性修复、健康监控以及本地 Web 恢复控制台Mobiledsh-mobileDeepSeek Harness 移动端适配与安全访问插件,支持局域网、远程连接、Android App 和手机浏览器。DSCODE@toddzheng024/dscode-bundle完整的 DeepSeek 编码代理,支持持久化 shell、Ultra 协作和自动权限审查。Auto Reviewdsh-auto-review针对 DeepSeek Harness 审批请求的第二模型 AI 自动审查:只读审查子代理在审批应答链上决定允许或拒绝,并采用故障关闭回退机制和完整的会话日志审计。

README

dsh-provider-rate-limit

English | 简体中文

Per-provider & per-model rate limiting for DeepSeek Harness LLM traffic, plus gateway identity rules (client spoofing) for restricted free-tier gateways.

适用于 DeepSeek Harness 的按供应商/模型粒度 LLM 限速插件,附带网关身份规则(客户端伪装)能力。

Features

  • Token-bucket rate limiting per (provider, model) route — smooth refill with burst support, idle-time recovery
  • Two modes when the bucket is empty:
    • wait — hold the request up to maxWaitMs, then let it through (transparent queueing)
    • reject — short-circuit immediately with a synthetic RATE_LIMIT response carrying providerRetryAfterMs
  • Strict FIFO — reservation-based design guarantees same-order admission without polling
  • Gateway identity rules — rewrite User-Agent / inject static headers for URLs matching a pattern (e.g. gateways that validate client identity), with a one-click OpenCode Zen preset
  • Master switch — flip enabled off to pass all traffic instantly, no listener re-registration
  • Settings UI card — full configuration from the Harness settings page, zh/en localized
  • Live stats line — compact readout in the composer dock (under the chat input), SSE-pushed in real time (no polling); hover to see per-route provider·model breakdown
  • SSE push endpoint — GET /api/provider-rate-limit.events streams a fresh stats snapshot every time counters change, with a 15 s heartbeat and automatic reconnection
  • Stats HTTP API — GET /api/provider-rate-limit.stats returns aggregate and per-route counters as JSON (used by the dock line; also available for external tooling)
  • Cross-plugin stats service — provider-rate-limit/stats service for in-process consumers (getStats, getAllStats, getAggregateStats, resetStats)
  • O(1) route lookup — pre-built Map for rule matching instead of linear scan
  • Standard ULID — 26-char Crockford base-32 IDs (48-bit big-endian time + 80-bit random)

Install

DSH plugin manager (recommended)

dsh plugin --profile web add github:jyao-SUSE-power-group/dsh-provider-rate-limit

Then restart DeepSeek Harness. The plugin registers itself into the llm service via its cordis patch.

Manual

git clone https://github.com/jyao-SUSE-power-group/dsh-provider-rate-limit.git ~/.dsh/plugins/dsh-provider-rate-limit
cd ~/.dsh/plugins/dsh-provider-rate-limit && pnpm install --prod

Configuration

Open Settings → 插件 → Provider Rate Limit. All options hot-reload — no restart needed.

OptionDefaultDescription
enabledtrueMaster switch; false passes everything untouched
requestsPerMinute20Global steady-state rate (applies when no route rule matches); 0 = unlimited
burst4Bucket capacity — how many requests may fire back-to-back
modewaitwait = queue up to maxWaitMs; reject = fail fast
maxWaitMs30000Longest queue time in wait mode before falling back to reject behavior
upstream429BackofftrueOn an upstream HTTP 429 (e.g. quota exhausted), pause the route until the window passes
backoffMs30000Initial cooldown (ms) when the upstream 429 carries no Retry-After; doubles on consecutive 429s up to maxBackoffMs
maxBackoffMs60000Maximum cooldown ceiling (ms) for exponential backoff; 0 = fixed cooldown (same as backoffMs)
backoffJitter0Symmetric jitter ratio (0–1) applied to the cooldown to prevent thundering herd; 0 = deterministic
maxConcurrentRequests0Maximum in-flight requests per route; 0 = unlimited concurrency
models[]Per-route overrides: match by provider/model substring, each with its own RPM/burst

Route rules

Route rules match on substrings of the resolved provider id and model name, e.g. provider opencode + model claude-*. The most specific matching rule wins; unmatched traffic uses the global limits.

Identity rules

Some free-tier gateways (e.g. OpenCode Zen) reject clients whose requests don't look like their official tooling. Identity rules let selected outbound URLs carry a different identity:

  • urlPattern — substring match against the request URL
  • userAgent — replacement User-Agent
  • dynamicIds — adds the per-request x-opencode-client/project/session/request header set
  • headers — arbitrary static headers (Name: Value pairs), applied last so they can override everything above

The fetch patch is ref-counted and unwinds cleanly: when the plugin deactivates, native fetch is restored exactly once, and a patch layered above ours in the meantime is never clobbered.

⚠️ Only spoof identities for services you are legitimately entitled to use, and in accordance with their terms.

How it works

Every outbound LLM stream passes through one llm/stream hook (a waterfall choke point covering agent loops, title generation, and compaction). Each call synchronously reserves a slot in the route's token bucket:

waitMs = bucket.reserve()        // exact wait, computed from a monotonic floor
if waitMs === 0                  → pass through immediately
else if mode=wait && ≤ maxWaitMs → sleep(waitMs), then pass
else                             → yield RATE_LIMIT finish (+ Retry-After hint)

The bucket floor is now − (capacity − 1) × interval, which gives classic burst-and-recover semantics: after idle time the bucket is implicitly full again, and resizing capacity/rate at runtime never mints a free burst.

Upstream 429 backoff

When the upstream provider answers with an HTTP 429 (e.g. workspace quota exhausted), the plugin watches the finish event and, if upstream429Backoff is on, puts that route into a cooldown window. New requests to that route queue (in wait mode, up to maxWaitMs) or reject (in reject mode) until the window passes, so the provider isn't hammered while it's already rejecting us. The window is providerRetryAfterMs (from the upstream Retry-After header) when present; otherwise backoffMs is used as the initial delay. On consecutive 429s without an intervening success, the delay doubles each time (exponential backoff), capped at maxBackoffMs. A symmetric backoffJitter ratio randomises the final value to prevent thundering herd. A successful (non-429) finish resets the backoff counter back to the base delay. The 429 finish itself is still forwarded, so dsh-llm-retry can also act on it.

Concurrency limiting

When maxConcurrentRequests > 0, the plugin additionally gates how many requests to a route may be in flight simultaneously. Requests that pass the RPM check but find all concurrency slots occupied join a FIFO slot queue and are granted the instant a predecessor releases — no polling, strict arrival order. This prevents a burst of parallel agents or subagents from overwhelming a provider even when individual RPM limits haven't been reached. 0 means unlimited concurrency (only RPM throttles).

Live Stats

The plugin renders a compact stats line in the composer dock (below the chat input):

限流统计 已拒绝 0 · 当前排队 0 · 累计排队 0 · 平均等待 — · 总请求 153 · 活跃路由 3

Hover over the line to see a per-route breakdown (provider·model + request count). The data is pushed in real time over SSE — the dock subscribes to the reactive stats store, so numbers jump the moment a request queues, rejects, or completes. No polling timers are involved; a 30 s fallback poll only kicks in if the SSE connection drops.

Push Endpoint (SSE)

GET /api/provider-rate-limit.events

A Server-Sent Events stream. Each frame is a complete stats snapshot:

data: {"aggregate":{"reserved":153,"waited":0,"totalWaitMs":0,"rejected":0,"queuedNow":0,"avgWaitMs":0,"routes":3},"routes":{...}}

A snapshot is sent immediately on connect, then again whenever counters move (request reserved, queue depth changed, request rejected or completed). The server also emits a : ping comment every 15 s to keep the connection alive through proxies.

Stats HTTP API

GET /api/provider-rate-limit.stats

Returns:

{
  "ok": true,
  "value": {
    "aggregate": { "reserved": 153, "waited": 0, "totalWaitMs": 0, "rejected": 0, "queuedNow": 0, "avgWaitMs": 0, "routes": 3 },
    "routes": {
      "opencode\u0000big-pickle": { "reserved": 117, "waited": 0, "queuedNow": 0, ... },
      "opencode-vision\u0000big-pickle": { "reserved": 34, ... },
      "amd-r\u0000DeepSeek-V4-Flash": { "reserved": 2, ... }
    }
  }
}

queuedNow is the live queue depth — how many requests are currently waiting in the rate-limit queue this instant (back to 0 as soon as the wait ends). waited remains the cumulative counter; the settings card shows both.

Cross-Plugin Stats API

Other plugins can query rate-limit statistics:

// In a plugin's apply(ctx):
const stats = ctx.get("provider-rate-limit/stats");

// Per-route stats
const routeStats = stats.getStats("opencode", "deepseek-v4-flash-free");
// → { reserved, waited, totalWaitMs, rejected, queuedNow, avgWaitMs, peekWaitMs }

// All routes
const all = stats.getAllStats();
// → { "opencode\u0000deepseek-v4-flash-free": {...}, ... }

// Aggregate across all routes
const agg = stats.getAggregateStats();
// → { reserved, waited, totalWaitMs, rejected, queuedNow, avgWaitMs, routes }

// Reset counters (for per-window accounting)
stats.resetStats();              // all routes
stats.resetStats("opencode", "v3"); // specific route

Development

pnpm install
npm test   # 31 tests: bucket behavior, FIFO, abort/reject, identity patch,
           # dispose, master switch, ULID format & uniqueness, stats service,
           # multi-provider, maxWaitMs timeout, hot-update retune, queuedNow
           # gauge, error handling, concurrency FIFO, legacy settings provider

Screenshots

Settings Card

Settings Card

Settings Configuration

Settings Config 1Settings Config 2

Composer Dock Live Stats

Composer Dock Stats

License

MIT