@naced/llm-multi-rate-limiter 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/LICENSE +22 -0
- package/README.md +67 -2
- package/README.zh.md +72 -0
- package/cordis.patch.yml +3 -0
- package/lib/client.js +691 -0
- package/lib/index.js +454 -0
- package/lib/status-rpc.js +285 -0
- package/lib/strategies/sliding-window.js +148 -0
- package/lib/strategies/token-bucket.js +168 -0
- package/lib/types/config.js +85 -0
- package/lib/types/index.js +1 -0
- package/package.json +59 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.0] - 2026-10-26
|
|
4
|
+
|
|
5
|
+
Fork of `@leaf233/dsh-llm-rate-limiter` 0.3.0, retargeted at the DSH 0.2.1 client contract.
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- **Settings UI**: the configuration form is now a `settings.section` entry (Settings → 多模型限速) instead of a `plugins.item` card. The old card never rendered on 0.2.1 shells whose sidebar comes from a third-party bundle, because `.dsh/market/*` page ownership — not this plugin — decides which page hosts `plugins.item`.
|
|
10
|
+
- The page owns its own `ConfigFormController` through `ctx.configForms.get("llm-multi-rate-limiter")` and binds it with `hooks: { snapshot: form.store }`, so it no longer depends on a host page passing `props.form`.
|
|
11
|
+
- Package renamed to `@naced/llm-multi-rate-limiter`; client no longer injects `dsh-client-ui-plugin-manager`.
|
|
12
|
+
- `plugins.row.config` entry point removed.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Model picker with a text field (`provider/model`) plus per-row RPM / concurrency / burst inputs and enable-remove actions.
|
|
17
|
+
- Effective-limit readout per model (override or inherited default).
|
|
18
|
+
- Bilingual dictionaries (zh/en) registered for the section, so labels follow the UI locale instead of hard-coded Chinese.
|
|
19
|
+
- Sidebar entry: `sidebar.panellist` registration (`order: 40`) plus the matching `main` panel, so the page is reachable from the app sidebar on shells that draw navigation there. Both surfaces share one `inject` factory.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **Fail-open interceptor**: if config parsing or a strategy throws, the call is now forwarded unthrottled with a warning instead of failing. Previously an exception escaped the `llm/stream` generator and every model call failed.
|
|
24
|
+
- Duplicate-limiter warning when `@leaf233/dsh-llm-rate-limiter` is also installed (both hook `llm/stream`, so calls would be limited twice).
|
|
25
|
+
|
|
26
|
+
### Security
|
|
27
|
+
|
|
28
|
+
- README documents exactly what the `llm/stream` position touches: `options.provider`, `options.model`, `options.signal` only; no prompt, response or credential access; no outbound network calls; no `fs` / `child_process` / `eval`; no install scripts.
|
|
29
|
+
- `engines.dsh` (`>=0.2.1-rc.2`) now states the tested runtime, so DSH's compatibility check has a real range to evaluate instead of relying on an unbounded peer range.
|
|
30
|
+
- `exports` gained `./package.json` (consistent with other DSH plugins; the loader's directory walk no longer has to carry it).
|
|
31
|
+
- Internal provider names removed from the README samples and the model input placeholder.
|
|
32
|
+
- LICENSE carries both copyright lines (upstream MIT + this fork).
|
|
33
|
+
|
|
34
|
+
### Unchanged
|
|
35
|
+
|
|
36
|
+
- Host half: `llm/stream` waterfall interception, token-bucket and sliding-window strategies, `/llm-multi-rate-limiter` status channel with its self-registered fallback route, queueing with `maxQueueWaitMs`.
|
|
37
|
+
- Settings storage: the profile entry's volatile `Config` references, written through `settings.mutate` into `cordis.patch.yml`.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dsh-llm-rate-limiter contributors (https://github.com/Leafyezi233/dsh-llm-rate-limiter)
|
|
4
|
+
Copyright (c) 2026 @naced/llm-multi-rate-limiter contributors
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,68 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @naced/llm-multi-rate-limiter
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Per-`provider/model` LLM rate limiting for DeepSeek Harness, with an editable **Settings** page (Settings → Multi-model limits) and a live status panel.
|
|
4
|
+
|
|
5
|
+
Forked from [`@leaf233/dsh-llm-rate-limiter`](https://github.com/Leafyezi233/dsh-llm-rate-limiter) 0.3.0 (MIT, © the upstream contributors). The configuration surface moved from the "built-in plugin config" card to a `settings.section` page and a sidebar entry; the card entry is gone.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Two strategies**: token bucket (bursts allowed) or sliding window (strict N per minute).
|
|
10
|
+
- **Per-model overrides**, keyed `provider/model`, e.g. `openai/gpt-5.1`.
|
|
11
|
+
- **Queue or reject** throttled calls (`onThrottled`, bounded by `maxQueueWaitMs`).
|
|
12
|
+
- **Live panel**: polls the `/llm-multi-rate-limiter` status channel once per second — per-model token/window usage, granted calls, average wait, recent events.
|
|
13
|
+
|
|
14
|
+
## Configuration
|
|
15
|
+
|
|
16
|
+
`~/.dsh/profiles/desktop/cordis.patch.yml`:
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
- id: llm-multi-rate-limiter
|
|
20
|
+
name: "@naced/llm-multi-rate-limiter"
|
|
21
|
+
config:
|
|
22
|
+
enabled: true
|
|
23
|
+
strategy: sliding-window
|
|
24
|
+
defaults:
|
|
25
|
+
maxConcurrent: 5
|
|
26
|
+
maxRpm: 60
|
|
27
|
+
burstSize: 10
|
|
28
|
+
refillRate: 1
|
|
29
|
+
models:
|
|
30
|
+
openai/gpt-5.1:
|
|
31
|
+
maxRpm: 20
|
|
32
|
+
maxConcurrent: 2
|
|
33
|
+
deepseek/deepseek-chat:
|
|
34
|
+
maxRpm: 60
|
|
35
|
+
maxConcurrent: 5
|
|
36
|
+
onThrottled: queue
|
|
37
|
+
maxQueueWaitMs: 240000
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- The row `id` is also the settings namespace (`dsh-settings` keys forms by `entry.options.id`), so keep it in step with the row.
|
|
41
|
+
- `models[<key>]` only needs the fields you override; the rest inherits `defaults`.
|
|
42
|
+
- Under the token bucket, an omitted `refillRate` (tokens/second) is derived from `maxRpm / 60`.
|
|
43
|
+
|
|
44
|
+
Edits made in the Settings page are written back to `cordis.patch.yml` immediately and hot-reload through `dsh-hmr`.
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
1. Place the package in the profile's `packages/llm-multi-rate-limiter` and add the dependency to the profile `package.json`:
|
|
49
|
+
```json
|
|
50
|
+
"@naced/llm-multi-rate-limiter": "file:./packages/llm-multi-rate-limiter"
|
|
51
|
+
```
|
|
52
|
+
2. Add `"@naced/llm-multi-rate-limiter"` to `dsh.profile.bundles`.
|
|
53
|
+
3. Append the `cordis.patch.yml` row above, then restart DSH.
|
|
54
|
+
|
|
55
|
+
## Security
|
|
56
|
+
|
|
57
|
+
This plugin intercepts the `llm/stream` waterfall, so it sits in front of every model call. What it actually does with that position:
|
|
58
|
+
|
|
59
|
+
- Reads only `options.provider`, `options.model` and `options.signal`. Prompts, messages, responses and credentials are never inspected, logged or transmitted.
|
|
60
|
+
- Makes no outbound network calls. The only HTTP surface is its own status channel (`/llm-multi-rate-limiter`), which is fenced by `connection.requestRejection()`, accepts `POST` + `application/json` only, and returns counters plus `provider/model` keys — no conversation content.
|
|
61
|
+
- Makes no filesystem or process calls (`fs`, `child_process`, `eval` are not imported); configuration is written through the host's settings service.
|
|
62
|
+
- Ships no install scripts.
|
|
63
|
+
|
|
64
|
+
If the limiter itself throws, the call is passed through untouched rather than failing, so a bug here cannot take the assistant offline.
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
MIT. Based on `@leaf233/dsh-llm-rate-limiter`; see [LICENSE](LICENSE) for both copyright lines.
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# @naced/llm-multi-rate-limiter
|
|
2
|
+
|
|
3
|
+
按 **provider/model** 限制 LLM 请求频率的 DeepSeek Harness 插件,带一个可编辑的「设置」页(Settings → 多模型限速),以及实时状态面板。
|
|
4
|
+
|
|
5
|
+
本包 fork 自 [`@leaf233/dsh-llm-rate-limiter`](https://github.com/Leafyezi233/dsh-llm-rate-limiter) 0.3.0(MIT,版权归上游作者),主要改动是把配置界面从「内置插件配置」卡片改为 `settings.section` 设置页 + 侧边栏入口,并移除了卡片入口。
|
|
6
|
+
|
|
7
|
+
## 功能
|
|
8
|
+
|
|
9
|
+
- **两种限速策略**:令牌桶 `token-bucket`(允许突发)/滑动窗口 `sliding-window`(严格每分钟 N 次)。
|
|
10
|
+
- **按模型独立配置**:key 为 `provider/model`,例如 `openai/gpt-5.1`。
|
|
11
|
+
- **排队或拒绝**:`onThrottled: queue` 时请求等待空位(受 `maxQueueWaitMs` 约束),`reject` 时立即返回错误。
|
|
12
|
+
- **实时面板**:每秒拉取 `/llm-multi-rate-limiter` 状态通道,显示各模型当前令牌/窗口占用、累计放行、平均等待,以及最近事件。
|
|
13
|
+
|
|
14
|
+
## 配置
|
|
15
|
+
|
|
16
|
+
配置写在 profile 的 `cordis.patch.yml`(`~/.dsh/profiles/desktop/cordis.patch.yml`):
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
- id: llm-multi-rate-limiter
|
|
20
|
+
name: "@naced/llm-multi-rate-limiter"
|
|
21
|
+
config:
|
|
22
|
+
enabled: true
|
|
23
|
+
strategy: sliding-window
|
|
24
|
+
defaults:
|
|
25
|
+
maxConcurrent: 5
|
|
26
|
+
maxRpm: 60
|
|
27
|
+
burstSize: 10
|
|
28
|
+
refillRate: 1
|
|
29
|
+
models:
|
|
30
|
+
openai/gpt-5.1:
|
|
31
|
+
maxRpm: 20
|
|
32
|
+
maxConcurrent: 2
|
|
33
|
+
deepseek/deepseek-chat:
|
|
34
|
+
maxRpm: 60
|
|
35
|
+
maxConcurrent: 5
|
|
36
|
+
onThrottled: queue
|
|
37
|
+
maxQueueWaitMs: 240000
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- 行 `id` 同时是设置命名空间(`dsh-settings` 按 `entry.options.id` 建表单),改名需与 `cordis.patch.yml` 一致。
|
|
41
|
+
- `models[<key>]` 只写需要覆盖的字段,其余继承 `defaults`。
|
|
42
|
+
- 令牌桶下 `refillRate`(个/秒)若省略,会按 `maxRpm / 60` 推导。
|
|
43
|
+
|
|
44
|
+
设置页里改任何字段都会立即写回 `cordis.patch.yml` 并热生效(`dsh-hmr` 监听 profile patch)。
|
|
45
|
+
|
|
46
|
+
## 安装
|
|
47
|
+
|
|
48
|
+
1. 把包放到 profile 的 `packages/llm-multi-rate-limiter`,并在 profile `package.json` 里加依赖:
|
|
49
|
+
```json
|
|
50
|
+
"@naced/llm-multi-rate-limiter": "file:./packages/llm-multi-rate-limiter"
|
|
51
|
+
```
|
|
52
|
+
2. `dsh.profile.bundles` 列表中加入 `"@naced/llm-multi-rate-limiter"`。
|
|
53
|
+
3. 在 `cordis.patch.yml` 加上面那段配置,重启 DSH。
|
|
54
|
+
|
|
55
|
+
## 卸载
|
|
56
|
+
|
|
57
|
+
删除 `cordis.patch.yml` 中该行与 `bundles` 里的包名,再删 `node_modules/@naced/llm-multi-rate-limiter` 即可。
|
|
58
|
+
|
|
59
|
+
## 安全说明
|
|
60
|
+
|
|
61
|
+
本插件拦截 `llm/stream` 瀑布,位于每一次模型调用之前。它到底用这个位置做了什么:
|
|
62
|
+
|
|
63
|
+
- 只读 `options.provider`、`options.model`、`options.signal`;不检查、不记录、不外发 prompt、messages、响应或凭据。
|
|
64
|
+
- 不发起任何对外网络请求。唯一的 HTTP 面是自带状态通道 `/llm-multi-rate-limiter`,由 `connection.requestRejection()` 加鉴权栅栏,只接受 `POST` + `application/json`,返回的是计数器与 `provider/model` 键,不含对话内容。
|
|
65
|
+
- 不使用 `fs`、`child_process`、`eval`;配置写入走宿主 settings 服务。
|
|
66
|
+
- 没有安装脚本。
|
|
67
|
+
|
|
68
|
+
限速器自身抛错时会原样放行请求,而不是让调用失败——这里的 bug 不会把助手整体弄挂。
|
|
69
|
+
|
|
70
|
+
## License
|
|
71
|
+
|
|
72
|
+
MIT。基于 `@leaf233/dsh-llm-rate-limiter`,双版权行见 [LICENSE](LICENSE)。
|
package/cordis.patch.yml
ADDED