@ds-hu/dsh-token-quota 2.5.0 → 2.6.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 +85 -2
- package/CONTEXT.md +10 -6
- package/LICENSE +24 -0
- package/README.en.md +357 -0
- package/README.md +55 -88
- package/docs/images/overview.png +0 -0
- package/docs/images/providers.png +0 -0
- package/lib/client.js +92 -34
- package/lib/index.js +135 -13
- package/lib/ledger.js +59 -0
- package/lib/usage.js +13 -2
- package/package.json +5 -2
- package/scripts/check-package.mjs +6 -1
- package/test/client.mjs +93 -3
- package/test/copy.mjs +6 -2
- package/test/metered.mjs +245 -0
- package/test/mock-dsh.mjs +12 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,8 +3,44 @@
|
|
|
3
3
|
本文件记录本插件的可见行为变更,格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
|
|
4
4
|
版本号遵循语义化版本。发布标签带 `fork-` 前缀,不与上游 `shxtmaker/dsh-token-quota` 的 `vX.Y.Z` 重名。
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
v2.0.x 的记录自 README 迁入本文件(见文末「更早版本」),v1.x 的变更散见 [docs/](docs/) 下的对应执行记录。
|
|
7
|
+
|
|
8
|
+
## [2.6.0] - 2026-11-05
|
|
9
|
+
|
|
10
|
+
### 新增
|
|
11
|
+
|
|
12
|
+
- **任意供应商的 token 统计(仅计量)**:DSH 里未归属到注册表供应商的路由,只要产生过一次真实调用,
|
|
13
|
+
就自动成为一条「仅计量」供应商行——只有今日 / 近 N 天的 token、五分量分布与归一比例,没有额度、
|
|
14
|
+
没有百分比、不发任何新的外部请求。此前这类路由的用量被整段丢弃,`今日总量` 因此比真实调用少一块。
|
|
15
|
+
- 仅计量行:不调度、不刷新、不取额度历史、不进关注限额与阈值分档;概览明细只留区间、用量、
|
|
16
|
+
归一比例、五分量与柱图(没有指标表,也没有「最后成功」——它从不查询)。
|
|
17
|
+
- 侧栏卡片在仅计量行上不画进度条:第 1 行照旧是名字与今日 chip,第 2 行给的就是这个窗口的量。
|
|
18
|
+
- 供应商页可给仅计量行改名(写 `meteredNames[route]`);没有启用开关,因为它不是一个可关掉的采集器。
|
|
19
|
+
- **DeepSeek 桌面登录与 API Key 并存不再分家**:`deepseek-account` 作为显式并表并入 `deepseek`,
|
|
20
|
+
同一账户只出现一行;同一 (session, turn, step) 的样本跨账本移动时先减后加,总量不双计。
|
|
21
|
+
- 路由后来被注册表收编时,`local:<route>` 的历史桶在读取时并入正式供应商,不从 0 开始,并入前后今日总量不变。
|
|
22
|
+
|
|
23
|
+
### 变更
|
|
24
|
+
|
|
25
|
+
- **今日总量改为「概览列表里每一行之和」**:一行只要有今日用量就算已添加、就出现在概览里、就计入合计,
|
|
26
|
+
因此可以逐行相加核对。「当前」标从此只表示小组件在用哪一家,不再等于「计入」。旧口径只加当前供应商,
|
|
27
|
+
于是没配 Key 的 `deepseek-account` 用量、以及被收编进未启用供应商的用量,会落进既不展示也不计入的账本
|
|
28
|
+
——小组件显示 1.0K、概览却报 0。
|
|
29
|
+
- **「近 N 天」按保留期标注**:`retentionDays` 小于 7 时,卡片、行内主指标与区间选项都写真实天数,
|
|
30
|
+
不再一律写「近 7 天」;区间选项并入既有的 `statsWindow`,删掉写死的 `range7d`。
|
|
31
|
+
- 文案净增 4 键(163 → 167):行状态、窗口量、改名按钮与改名页的两个字段名。
|
|
32
|
+
|
|
33
|
+
### 修复
|
|
34
|
+
|
|
35
|
+
- **收编后的替换样本不再被重复计入**:记录器的扣减跟着账本搬家走(`ledgerMoves`),在途步骤再报一次
|
|
36
|
+
相同样本时是替换而不是第二次累加——此前会变成两倍,且写进 `usage.json` 后整段保留期内都不会自愈。
|
|
37
|
+
|
|
38
|
+
### 文档
|
|
39
|
+
|
|
40
|
+
- 新增**英文 README**(`README.en.md`)与 npm/CI/许可证/DSH 版本四个徽章,两份文档顶部互相链接,
|
|
41
|
+
随包分发的截图也一并进了打包契约断言。
|
|
42
|
+
- README 顶部只保留最近两版更新记录,v2.0.0–v2.0.5 迁进本文件的「更早版本」,两份文件不再各写一遍。
|
|
43
|
+
- 新增 **`LICENSE`**(MIT),一并保留上游 shxtmaker 的版权声明;此前的许可证只有 `package.json` 里的一行。
|
|
8
44
|
|
|
9
45
|
## [2.5.0] - 2026-11-03
|
|
10
46
|
|
|
@@ -154,3 +190,50 @@
|
|
|
154
190
|
不画一条 0% 的空条。
|
|
155
191
|
- Token 量级统一 3 位有效数字(`1.32M`、`12.0K`、`999.6K → 1.00M`),不再固定一位小数。
|
|
156
192
|
- 用量浮卡不再重复计费时段块(档位与倒计时由常驻卡片承担);缺次年告警移到设置页覆盖表旁。
|
|
193
|
+
|
|
194
|
+
## 更早版本
|
|
195
|
+
|
|
196
|
+
自 README 的「vX.Y.Z 更新」小节迁入,原记录没有日期。
|
|
197
|
+
|
|
198
|
+
## [2.0.5]
|
|
199
|
+
|
|
200
|
+
- 修复智谱/Z.ai Coding Plan 查询失效:供应商已把用量窗口的类型名由 `TOKENS_LIMIT` 改名为 `CREDIT_LIMIT`,
|
|
201
|
+
插件此前只认旧名,窗口全部被跳过,供应商显示为「暂时无法获取」。
|
|
202
|
+
- 窗口改按 `unit` 标识分类(5 小时窗口、周窗口、月度 MCP 上限),不再依赖数组位置;新增周窗口与供应商
|
|
203
|
+
公布的重置时刻。新旧拼写并存时都能读取,重复或无法命名的窗口如实报错,不猜一个窗口顶上。
|
|
204
|
+
- 业务失败改按响应信封判定:密钥失效(HTTP 200 响应体内的 `code:401`)报鉴权失败,不再误报成
|
|
205
|
+
「响应缺少 data.limits」。
|
|
206
|
+
|
|
207
|
+
## [2.0.4]
|
|
208
|
+
|
|
209
|
+
- 修复 Command Code 等供应商未公布重置时刻时错误显示「1月1日」的问题。
|
|
210
|
+
- 统一验证日期文案与原始时刻,零值、无效日期和误传入毫秒字段的秒级值显示为未知,不推算重置时间。
|
|
211
|
+
- 保留有效毫秒、数字串和带时区日期的准确时刻,OpenCode Go 的正常窗口倒计时保持不变。
|
|
212
|
+
|
|
213
|
+
## [2.0.3]
|
|
214
|
+
|
|
215
|
+
- 点击侧栏打开贴在卡片上方的用量浮卡,显示供应商主指标、查询状态、刷新间隔和上次刷新时间。
|
|
216
|
+
- 浮卡底部提供「详情」「设置」「关闭」;完整供应商明细和现有配置面板继续保留。
|
|
217
|
+
- 浮卡适配完整、紧凑和图标侧栏,支持再次点击、Esc 和外部点击关闭,随窗口变化调整位置。
|
|
218
|
+
|
|
219
|
+
## [2.0.2]
|
|
220
|
+
|
|
221
|
+
- 修复停用、重新启用和宿主重启插件时的 `webserver: duplicate exact route` 启用失败。
|
|
222
|
+
- 启动失败时释放已登记的资源;某项清理报错不会阻止其他资源释放。
|
|
223
|
+
|
|
224
|
+
## [2.0.1]
|
|
225
|
+
|
|
226
|
+
- 侧栏单击恢复独立「供应商限额明细」弹窗,按 v1.4.0 分栏展示已添加供应商与周期指标,刷新历史恢复为表格,
|
|
227
|
+
沿用当前主题配色和按钮样式。
|
|
228
|
+
- 详情中的「设置」按钮进入现有概览、供应商、设置面板;保留完整/紧凑侧栏和显示偏好。
|
|
229
|
+
- 修复供应商扫描中的 `cannot get required service "settings" in inactive context` 错误;设置服务暂不可用时
|
|
230
|
+
保留最近成功目录,恢复后可重新扫描。
|
|
231
|
+
|
|
232
|
+
## [2.0.0]
|
|
233
|
+
|
|
234
|
+
- 侧栏支持完整与紧凑显示,单击直接打开概览,显示偏好自动保存。
|
|
235
|
+
- 用量监控面板提供「概览」「供应商」「设置」三个页签,侧栏入口与宿主设置入口使用相同内容。
|
|
236
|
+
- 概览支持需关注筛选、自适应一列或两列布局,保留各周期与币种的独立指标。
|
|
237
|
+
- 配置编辑保留未保存草稿,提供放弃修改确认;保存失败保留输入,避免旧请求覆盖新的编辑内容。
|
|
238
|
+
- 查询失败时保留上次成功数据并标明状态;未知值与真实零值分别显示。
|
|
239
|
+
- 适配 Windows 桌面端的当前会话选择、原生设置入口和侧栏收起/恢复。
|
package/CONTEXT.md
CHANGED
|
@@ -5,9 +5,13 @@ DeepSeek Harness 中的供应商额度、余额、报告费用和用量监控。
|
|
|
5
5
|
## Language
|
|
6
6
|
|
|
7
7
|
**供应商(Supplier)**:
|
|
8
|
-
一个可独立配置凭据并查询额度、余额或报告的供应商条目。同名服务的普通 API Key、Management Key、组织 Admin Key
|
|
8
|
+
一个可独立配置凭据并查询额度、余额或报告的供应商条目。同名服务的普通 API Key、Management Key、组织 Admin Key 以及不同地域属于不同条目。没有可查询能力的路由由「仅计量供应商」承载,不是这种条目。
|
|
9
9
|
_Avoid_: 按显示名称合并、通用账户
|
|
10
10
|
|
|
11
|
+
**仅计量供应商(Metered Supplier)**:
|
|
12
|
+
DSH 路由未归属到任何注册表供应商时,由它的真实用量自动派生的一条供应商行。只有经过 Harness 的 Token(今日、近 N 天、五分量与归一比例),没有可查询的额度、百分比或重置时间;行由流量产生而不是配置出来,因此不能手工添加、不能停用,只能改名;本地用量按保留期清理后这一行随之消失。它存在期间恒计入今日用量。路由后来被注册表收编时,历史并入正式供应商,不另开一行,并入后仍计入总量。
|
|
13
|
+
_Avoid_: 自定义额度查询、可配置的第三方接口、按供应商账单补齐
|
|
14
|
+
|
|
11
15
|
**凭据类别(Credential Class)**:
|
|
12
16
|
查询所需的授权类别,例如普通 API Key、Management Key、组织 Admin Key。不同类别不能替代,自动识别普通聊天密钥不代表具有组织账务权限。
|
|
13
17
|
_Avoid_: 密钥类型下拉框
|
|
@@ -95,12 +99,12 @@ _Avoid_: 浏览器前台窗口、后台活跃会话
|
|
|
95
99
|
_Avoid_: 当前供应商清单
|
|
96
100
|
|
|
97
101
|
**当前供应商(Current Supplier)**:
|
|
98
|
-
|
|
99
|
-
_Avoid_:
|
|
102
|
+
按照现有启用配置与近期流量规则选出的供应商集合;流量不可观测时沿用启用清单。它决定小组件的「当前在用」与概览行上的「当前」标,**不是**今日用量的汇总口径——只看它会让「有 token 但不在当前集」的行凭空消失。
|
|
103
|
+
_Avoid_: 当前会话供应商、今日总量的口径
|
|
100
104
|
|
|
101
105
|
**今日用量(Daily Usage)**:
|
|
102
|
-
|
|
103
|
-
_Avoid_:
|
|
106
|
+
概览列表里每一行(已添加供应商,含仅计量供应商)的今日 Token 用量之和,按宿主本地日统计。不变式:一行只要有今日用量,它就必须出现在列表里、并且计入总和——否则这个数字会比真实调用少一块。它既不是当前会话用量,也不是全部历史路由的当日总量。峰谷拆分只在 DeepSeek 名下给出,且仍按同一本地日口径逐小时归属。
|
|
107
|
+
_Avoid_: 全局今日总量、会话今日量、只按当前供应商求和
|
|
104
108
|
|
|
105
109
|
**用量分布(Usage Breakdown)**:
|
|
106
110
|
一次调用或一个自然日的 Token 按互不相交的五个分量记账:未缓存输入、输出、缓存命中、缓存写入与未细分。前四项之和即总量;只有上游确实没有给出任何分量时才把总量记入未细分,绝不与分量重复相加。
|
|
@@ -151,7 +155,7 @@ _Avoid_: 详情弹窗、分栏明细
|
|
|
151
155
|
_Avoid_: 已生效配置
|
|
152
156
|
|
|
153
157
|
**已添加供应商(Added Supplier)**:
|
|
154
|
-
|
|
158
|
+
最近成功扫描发现、已启用、已经填写任一密钥,或已经产生过真实用量的供应商。仅修改阈值或地址不算添加,已停用但保留密钥的供应商仍属于目录;仅计量供应商一旦有一条用量就属于已添加。
|
|
155
159
|
_Avoid_: 已启用供应商
|
|
156
160
|
|
|
157
161
|
**可添加供应商(Addable Supplier)**:
|
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 shxtmaker — upstream dsh-token-quota
|
|
4
|
+
https://github.com/shxtmaker/dsh-token-quota
|
|
5
|
+
Copyright (c) 2026 ds-hu — this fork
|
|
6
|
+
https://github.com/ds-hu/dsh-usage-monitor
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
in the Software without restriction, including without limitation the rights
|
|
11
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
furnished to do so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
SOFTWARE.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
# dsh-token-quota
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@ds-hu/dsh-token-quota)
|
|
4
|
+
[](https://github.com/ds-hu/dsh-usage-monitor/actions/workflows/verify.yml)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](#install)
|
|
7
|
+
|
|
8
|
+
A usage monitor for DeepSeek Harness: periodic limits, account balances, reported spend and today's token count for
|
|
9
|
+
the supplier behind the current session — plus token statistics for any supplier the plugin does not know. Works in the
|
|
10
|
+
Windows desktop app and in the Web UI.
|
|
11
|
+
|
|
12
|
+
English · [中文](README.md)
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
Current version: **v2.6.0**. Requires **DSH ≥ 0.1.7-rc.2**; real desktop and Web verification runs on **DSH 0.2.0-rc.2**.
|
|
17
|
+
|
|
18
|
+
The Plugins panel shows it as **Usage monitor** (Chinese **用量监控**): the icon is `icon.svg` in the package root, and the
|
|
19
|
+
title and one-line description come from `meta` in `locale/zh.json` and `locale/en.json`.
|
|
20
|
+
|
|
21
|
+
[npm](https://www.npmjs.com/package/@ds-hu/dsh-token-quota) · [Issues](https://github.com/ds-hu/dsh-usage-monitor/issues)
|
|
22
|
+
|
|
23
|
+
## What's new in v2.6.0
|
|
24
|
+
|
|
25
|
+
- **Token statistics for any supplier.** An LLM route that is not one of the built-in suppliers becomes a
|
|
26
|
+
**"usage only"** row after its first real call: today and the last N days of tokens, the five-part breakdown and the
|
|
27
|
+
normalised ratio — no quota query, no percentage, no new outbound request. Those tokens used to be dropped entirely.
|
|
28
|
+
- **Today's total is now the sum of the rows you can see.** Any row with today's usage is listed and counted, so the
|
|
29
|
+
number can be checked by adding the rows up. The "current" mark now only says which supplier the widget is showing,
|
|
30
|
+
not which row is counted.
|
|
31
|
+
- **DeepSeek desktop sign-in and API key are one row.** Tokens from the desktop login are counted as well; only the
|
|
32
|
+
balance query still needs an API key.
|
|
33
|
+
- When a route is later adopted by a built-in supplier its history moves with it instead of restarting at zero, and a
|
|
34
|
+
replacement sample that arrives mid-adoption is no longer counted twice.
|
|
35
|
+
- "Last N days" reads N from the usage retention setting instead of always saying 7.
|
|
36
|
+
|
|
37
|
+
## What's new in v2.5.0
|
|
38
|
+
|
|
39
|
+
- The "Today" label in an expanded row became a range picker (today / last 7 days); the token count, the ratio and the
|
|
40
|
+
five-part bar all follow that range, while the chart stays on 7 days.
|
|
41
|
+
- Each window (5h / week / month) is estimated in tokens, switching between "left" and "plan total", with the sampling
|
|
42
|
+
interval, the numerator and denominator, and the ±1pp band on hover.
|
|
43
|
+
- Estimates are derived from the slope (local tokens ÷ Δpp) rather than from cumulative used %, which halved the total
|
|
44
|
+
whenever the window was longer than the local history.
|
|
45
|
+
- Bar labels are no longer struck through by the quota line: each sits on a card-coloured plate and the line passes behind
|
|
46
|
+
it.
|
|
47
|
+
|
|
48
|
+
Earlier releases are recorded in [CHANGELOG](CHANGELOG.md).
|
|
49
|
+
|
|
50
|
+
## Install
|
|
51
|
+
|
|
52
|
+
The plugin is published on npm as **`@ds-hu/dsh-token-quota`**. For offline deployment run `npm pack` in the source
|
|
53
|
+
directory to get `ds-hu-dsh-token-quota-2.6.0.tgz` and install that archive. The package does not contain DeepSeek
|
|
54
|
+
Harness itself; the first install may need to download dependencies.
|
|
55
|
+
|
|
56
|
+
### Windows desktop app
|
|
57
|
+
|
|
58
|
+
Start DeepSeek Harness Desktop once so it initializes, then quit it completely. Use the CLI shipped with the install
|
|
59
|
+
directory and add the plugin to the **`desktop` profile**. Adjust the paths to your own installation.
|
|
60
|
+
|
|
61
|
+
```powershell
|
|
62
|
+
$desktopCli = 'D:\AI\DeepSeek- Harness\resources\runtime\cli\bin\dsh.cmd'
|
|
63
|
+
& $desktopCli plugin --profile desktop add @ds-hu/dsh-token-quota
|
|
64
|
+
& $desktopCli plugin --profile desktop list --depth 0
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
For an offline install, pass the archive instead of the package name:
|
|
68
|
+
|
|
69
|
+
```powershell
|
|
70
|
+
$archivePath = (Resolve-Path './ds-hu-dsh-token-quota-2.6.0.tgz').Path
|
|
71
|
+
& $desktopCli plugin --profile desktop add "file:$archivePath"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Reopen the app and expand the left sidebar to see the widget; it is also reachable from Settings → Usage monitor. A
|
|
75
|
+
plugin installed into the `web` profile does not appear in the desktop app. The widget hides with the sidebar and comes
|
|
76
|
+
back when the sidebar is expanded again.
|
|
77
|
+
|
|
78
|
+
### Web / CLI
|
|
79
|
+
|
|
80
|
+
Install DeepSeek Harness first and check that `dsh --version` runs. The examples use the `web` profile; substitute your
|
|
81
|
+
own profile name.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
dsh plugin --profile web add @ds-hu/dsh-token-quota
|
|
85
|
+
dsh --profile web
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Offline install (run `npm pack` first to get the archive):
|
|
89
|
+
|
|
90
|
+
Linux / macOS:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
dsh plugin --profile web add "file:$(pwd)/ds-hu-dsh-token-quota-2.6.0.tgz"
|
|
94
|
+
dsh --profile web
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Windows PowerShell:
|
|
98
|
+
|
|
99
|
+
```powershell
|
|
100
|
+
$archivePath = (Resolve-Path './ds-hu-dsh-token-quota-2.6.0.tgz').Path
|
|
101
|
+
dsh plugin --profile web add "file:$archivePath"
|
|
102
|
+
dsh --profile web
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
If an older version reported duplicate routes, quit DSH completely, install v2.0.4 or later, and start it again to clear
|
|
106
|
+
the routes left behind by the running process.
|
|
107
|
+
|
|
108
|
+
Finish the current task and quit the DSH instance before installing or upgrading. To upgrade from an archive, run `add`
|
|
109
|
+
again with the new package, then restart DSH and refresh the Web page.
|
|
110
|
+
|
|
111
|
+
### From source
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
git clone https://github.com/ds-hu/dsh-usage-monitor.git
|
|
115
|
+
cd dsh-usage-monitor
|
|
116
|
+
npm ci
|
|
117
|
+
dsh plugin --profile web add "link:$(pwd)"
|
|
118
|
+
dsh --profile web
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
In PowerShell, replace the link command with:
|
|
122
|
+
|
|
123
|
+
```powershell
|
|
124
|
+
$pluginDirectory = (Get-Location).Path
|
|
125
|
+
dsh plugin --profile web add "link:$pluginDirectory"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
A link install uses the source directory directly, so keep it and its dependencies around. To update, run
|
|
129
|
+
`git pull --ff-only` and `npm ci`, then restart DSH.
|
|
130
|
+
|
|
131
|
+
## Getting started
|
|
132
|
+
|
|
133
|
+
1. Click the sidebar card to open the **Usage monitor** panel; it opens on **Overview** in both wide and narrow layouts.
|
|
134
|
+
2. Expand a supplier in **Overview** to see every metric, today's breakdown, the billing tier and the usage chart; the
|
|
135
|
+
**Configure** button in the expanded area jumps to that supplier.
|
|
136
|
+
3. Or switch to the **Suppliers** tab and press **Rescan** to pick up the ordinary API keys already configured in the
|
|
137
|
+
harness; suppliers that need a higher-privilege credential are configured by hand.
|
|
138
|
+
4. Open a supplier, fill in the required fields, enable it and save. Leaving a secret field empty keeps the old value.
|
|
139
|
+
5. Use **Test connection** to check what you saved; query interval, retention and the holiday override live in the
|
|
140
|
+
collapsible **Global settings** at the bottom of the Suppliers tab.
|
|
141
|
+
|
|
142
|
+
**Secrets are written two ways.** Every secret field accepts either the **key itself** (`apiKey`, saved as a redacted
|
|
143
|
+
`role('secret')` field) or only a **credential reference** (`apiKeyEnv`: the name of a record in the DSH credential store
|
|
144
|
+
or of an environment variable, e.g. `COMMAND_CODE_API_KEY`). A reference is resolved in host memory from the DSH
|
|
145
|
+
credential store and then the process environment, so the key itself never lands in the plugin config; `/state` only
|
|
146
|
+
reports the reference name and whether it resolved. A rescan writes references only (`apiKeyEnv`) and no longer copies
|
|
147
|
+
keys into the profile config. When both exist the key itself wins, and **either one counts as a manual takeover**: a
|
|
148
|
+
rescan stops touching that supplier's secret fields. "Test connection" also resolves a reference typed into the editor
|
|
149
|
+
but not yet saved, so you do not have to save first.
|
|
150
|
+
|
|
151
|
+
**The DeepSeek desktop login counts tokens; the balance still needs an API key.** Calls made through the desktop login
|
|
152
|
+
arrive as the `deepseek-account` route and the plugin merges them into the same DeepSeek row, so today and the last N days
|
|
153
|
+
of tokens are visible without any key. The balance can only be queried with an API key: if that is all you want, fill in
|
|
154
|
+
the key of the same account in the existing DeepSeek supplier, or configure the harness's DeepSeek API key route and
|
|
155
|
+
rescan.
|
|
156
|
+
|
|
157
|
+
## Sidebar and panel
|
|
158
|
+
|
|
159
|
+
The expanded sidebar has three parts: the **plan name** (the supplier's display name, never the model), the **watched
|
|
160
|
+
limit bars** (one or more, each with its own short label, used percentage and reset countdown) and the always-visible
|
|
161
|
+
**billing tier** (peak/off-peak and the next switch). Threshold colours live on the bars: green < warning < yellow <
|
|
162
|
+
critical < red; with several bars each is coloured by its own percentage and all share the same column widths. Without
|
|
163
|
+
watched limits the card falls back to the weekly window, then to the tightest valid window; balance-only and
|
|
164
|
+
report-only suppliers keep text instead of a bar, and stale or disabled suppliers stay neutral. Today's token count no
|
|
165
|
+
longer takes a sidebar line — it is shown per supplier in the overview rows (and is still in the accessible label).
|
|
166
|
+
A **usage only** row, which has nothing to query, draws no bar and puts its own window total on line 2 instead. Token
|
|
167
|
+
counts always use 3 significant digits (`1.32M`, `12.0K`). The compact sidebar keeps the supplier name and the primary
|
|
168
|
+
metric text. A separate chevron toggles the display; the preference is stored in the current browser; a narrow sidebar
|
|
169
|
+
switches to compact automatically and restores your choice when it widens again.
|
|
170
|
+
|
|
171
|
+
**Watched limits** are ticked in a supplier's Configure page: the tick order is the card order, ↑↓ reorders within the
|
|
172
|
+
row, and nothing ticked means the default rule. Candidates come from the last successful query's identifiable windows
|
|
173
|
+
(`5h rolling`, `weekly`, `monthly`, `allowance`, …); a ticked but currently missing window is marked unavailable and
|
|
174
|
+
skipped, and comes back with the data. The setting affects the second card line only, never the overview, the compact
|
|
175
|
+
row or the primary metric of the detail view.
|
|
176
|
+
|
|
177
|
+
Clicking the sidebar card opens the **Usage monitor** panel. It has two tabs, **Overview** and **Suppliers**; the card
|
|
178
|
+
opens on Overview, and the host's Settings → Usage monitor opens on Suppliers. In dialog form, Esc, a click on the
|
|
179
|
+
backdrop or **Close** dismisses it and returns focus to the card.
|
|
180
|
+
|
|
181
|
+
The overview lists the added suppliers with name, status, primary metric and today's count (a **usage only** row appears
|
|
182
|
+
there too, with the status "usage only"), one expanded row at a time. The total above the list is the sum of those rows'
|
|
183
|
+
today counts, so it can be checked row by row. An expanded row shows the metric tables grouped by quota, balance and
|
|
184
|
+
report, today's five-part breakdown (a single five-part bar) with the **normalised ratio** ("cache hit : cache miss :
|
|
185
|
+
output" with miss fixed at 1, e.g. `30.0 : 1.00 : 0.150`, three significant digits each), DeepSeek's billing-tier split,
|
|
186
|
+
and a **combined bar-and-line chart**: bars are daily token counts, each non-empty bar is labelled (only the peak when the
|
|
187
|
+
window is long) and the window total sits above the chart; lines are the remaining quota per window on the same time
|
|
188
|
+
axis, broken where the percentage drops (a new window) with the current remaining percentage in the legend. Quota history
|
|
189
|
+
is fetched on demand on the first expansion and reused for the rest of the panel session. The collapsed refresh history
|
|
190
|
+
table shows the last 50 entries.
|
|
191
|
+
|
|
192
|
+
The **Suppliers** tab lists the added directory, enable switches, configuration entries and a rescan; a collapsible
|
|
193
|
+
**Global settings** block at the bottom holds the query interval, the usage retention and the holiday override (a
|
|
194
|
+
missing next year is called out next to the summary) plus the sidebar display preference. Addable suppliers start
|
|
195
|
+
collapsed.
|
|
196
|
+
|
|
197
|
+

|
|
198
|
+
|
|
199
|
+
| Tab | Contents |
|
|
200
|
+
| --- | --- |
|
|
201
|
+
| Overview | Today's total, all/attention filter, expandable supplier details, collapsed refresh history. |
|
|
202
|
+
| Suppliers | Added directory, enable switches, configuration entries, rescan, global settings, sidebar display, addable directory. |
|
|
203
|
+
|
|
204
|
+
The query interval defaults to **60 s** (range **10–3600 s**); the usage retention defaults to **7 days** (range
|
|
205
|
+
**1–90 days**). Edits survive background refreshes and tab switches; going back, cancelling or closing inside the plugin
|
|
206
|
+
asks before discarding unsaved changes. Leaving the host's native settings section destroys the panel and cannot keep
|
|
207
|
+
an unsaved draft.
|
|
208
|
+
|
|
209
|
+
## What the numbers mean
|
|
210
|
+
|
|
211
|
+
- **Today's usage**: the sum of today's tokens, by the host's local day, of every row in the overview (added suppliers,
|
|
212
|
+
including usage-only ones). A row with today's usage is always listed, so the total adds up row by row. Calls made by
|
|
213
|
+
a standalone CLI or another application are not included.
|
|
214
|
+
- **Usage breakdown**: today's usage split into DeepSeek Harness's five disjoint parts (uncached input, output, cache
|
|
215
|
+
hit, cache write, unsplit); the five always sum to the total. The ratio uses only the first three, normalised so that
|
|
216
|
+
cache miss = 1.
|
|
217
|
+
- **Remaining quota**: derived as `100 − used %`. Quota only grows within a window, so a falling percentage means a new
|
|
218
|
+
window and the line breaks there. This only applies to windows with a percentage (`5h`, week, month, …); balances and
|
|
219
|
+
reported spend have none and never appear on that line.
|
|
220
|
+
- **Periodic limits**: the percentage is the used share. The card's second line shows the **watched limits** you
|
|
221
|
+
configured (several, in your order); without configuration it takes the weekly window, then the tightest valid one.
|
|
222
|
+
Each bar's reset time always belongs to its own window. The overview and the compact sidebar still use the tightest
|
|
223
|
+
valid window as the primary metric.
|
|
224
|
+
- **Billing tier**: DeepSeek's account-level peak/off-peak pricing (judged in Beijing time) is an account fact, so it is
|
|
225
|
+
always on the card's last line; how today's usage splits across tiers is given per supplier in the expanded overview
|
|
226
|
+
row only. A missing next-year holiday schedule is called out in Global settings.
|
|
227
|
+
- **Balance**: shown per currency, never converted or summed.
|
|
228
|
+
- **Reported spend and reported usage**: kept in the period the supplier reports, shown separately from the local
|
|
229
|
+
today's token count.
|
|
230
|
+
- **Unknown vs zero**: missing or unknown values show `—`, a real zero shows `0`; a session with no call yet shows "no
|
|
231
|
+
calls yet".
|
|
232
|
+
- **Failed refresh**: with old data the row shows "update failed · last data" plus the time of the last success; without
|
|
233
|
+
old data it shows "temporarily unavailable".
|
|
234
|
+
|
|
235
|
+
Switching sessions never borrows another session's supplier. A failed refresh keeps the previous result for the same
|
|
236
|
+
configuration; changing a supplier's query configuration clears that supplier's old result.
|
|
237
|
+
|
|
238
|
+
## Supported suppliers
|
|
239
|
+
|
|
240
|
+
| Supplier | What is queried | Credential | Setup |
|
|
241
|
+
| --- | --- | --- | --- |
|
|
242
|
+
| DeepSeek | Account balance, multi-currency | API key | auto-detected or manual |
|
|
243
|
+
| OpenRouter | Current key's period quota and today's spend | API key | auto-detected or manual |
|
|
244
|
+
| OpenRouter account | Account credits | Management key | manual |
|
|
245
|
+
| OpenAI organization | Last complete UTC day's usage and cost | Organization admin key | manual |
|
|
246
|
+
| Anthropic organization | Organization usage and cost | Organization admin key | manual |
|
|
247
|
+
| Moonshot (CN / intl.) | Account balance | API key | auto-detected or manual |
|
|
248
|
+
| Z.ai / Zhipu Coding Plan | Plan window limits | API key | auto-detected or manual |
|
|
249
|
+
| MiniMax (CN / intl.) | Token Plan window limits | API key | auto-detected or manual |
|
|
250
|
+
| OpenCode (compatible source) | 5h, weekly and monthly windows plus allowance | API key / OAuth | auto-detected or manual |
|
|
251
|
+
| Command Code (compatible source) | 5h and weekly windows plus plan monthly quota | API key | auto-detected or manual |
|
|
252
|
+
|
|
253
|
+
Ordinary API keys, management keys and admin keys are configured separately. The plugin never uses a chat key against
|
|
254
|
+
an organization management endpoint, never overwrites a key you typed, and never re-enables a supplier you disabled.
|
|
255
|
+
|
|
256
|
+
### Any other supplier (usage only)
|
|
257
|
+
|
|
258
|
+
Suppliers missing from the table above still get token statistics: an LLM route in the harness that belongs to none of
|
|
259
|
+
them shows up in the overview as a **"usage only"** row after one real call — today and the last N days of tokens, the
|
|
260
|
+
five-part breakdown and the ratio, with no quota query, no percentage and no new outbound request. These tokens used to
|
|
261
|
+
be dropped, which made the total smaller than the real traffic.
|
|
262
|
+
|
|
263
|
+
- The row is produced by traffic: it cannot be added by hand and cannot be disabled (there is no collector to switch
|
|
264
|
+
off); it can be renamed on the Suppliers tab, defaulting to the route id or the harness display name. It comes and
|
|
265
|
+
goes with the local usage: once the retention period (7 days by default) has no fresh usage and the buckets are
|
|
266
|
+
pruned, the row disappears.
|
|
267
|
+
- The card's first line keeps the name and today's count; line 2 has no bar and shows this window's own total (the last
|
|
268
|
+
N days, where N comes from the retention setting).
|
|
269
|
+
- These rows always count towards today's total, but never into the attention filter, watched limits or threshold
|
|
270
|
+
colours; the expanded view has no metric table and no "data time" — it never queries.
|
|
271
|
+
- If the plugin later supports that route, the history stored under `local:<route>` moves into the real supplier instead
|
|
272
|
+
of restarting at zero, and today's total does not change across the move.
|
|
273
|
+
- The DeepSeek desktop login (`deepseek-account`) and the API key are two paths to the same account and merge into one
|
|
274
|
+
DeepSeek row, so nothing is counted twice; with a login but no queryable key the row is still listed and counted, it
|
|
275
|
+
just reports "not queried" as its status.
|
|
276
|
+
|
|
277
|
+
Official queries only accept the supplier's HTTPS host and known base paths; a URL that does not match is never called.
|
|
278
|
+
OpenCode and Command Code use compatible endpoints whose availability is up to the supplier. The table describes what the
|
|
279
|
+
plugin can query, not that every real account has been verified.
|
|
280
|
+
|
|
281
|
+
## Data storage and upgrades
|
|
282
|
+
|
|
283
|
+
Configuration lives in the plugin row of the profile; secret fields use the host's secret mechanism. Leaving a secret
|
|
284
|
+
field empty in the UI keeps it; to clear it, edit the `id: dsh-token-quota` entry in
|
|
285
|
+
`$DSH_HOME/profiles/<profile>/cordis.patch.yml`.
|
|
286
|
+
|
|
287
|
+
Local token usage is stored per supplier × hour × component in `$DSH_HOME/dsh-token-quota/usage.json` and pruned to the
|
|
288
|
+
retention period. The file is `version: 2` with five disjoint parts per hour bucket: uncached input, output, cache hit,
|
|
289
|
+
cache write and unsplit (the first four sum to the total). A version 1 file is read with its total folded into "unsplit"
|
|
290
|
+
— no breakdown is guessed and no total is lost — and written back as version 2 on the next save. An older plugin reads
|
|
291
|
+
version 2 as unsupported and keeps the original file. The refresh history is kept in memory only and cleared on restart.
|
|
292
|
+
|
|
293
|
+
Quota history lives next to it in `quota.json` (`version: 1`): the **change points of the used percentage** per supplier
|
|
294
|
+
and metric (`[time, used %]`), with unchanged values not recorded. It is kept for **14 days**, at most 600 points per
|
|
295
|
+
metric, sharing one debounced write and one short write lock with the usage file and merged across processes by time
|
|
296
|
+
(merging twice does not double the points). It is transferred on demand: only the first expansion of a supplier requests
|
|
297
|
+
`/state?quota=1`, which is clipped to the displayed window and downsampled to ≤120 points and reused for the rest of the
|
|
298
|
+
panel session; the always-on card poll never carries it. A corrupt file or an unknown version is treated as "no history"
|
|
299
|
+
and the file is preserved; the card and today's usage are unaffected.
|
|
300
|
+
|
|
301
|
+
When upgrading from an old version, the plugin reads the `dsh-token-quota` / `quota-monitor` configuration from the old
|
|
302
|
+
`settings.yaml` or `settings.yaml.imported` if the current row has no user configuration, and keeps the source file. The
|
|
303
|
+
old `quota-monitor` usage directory is migrated only when the new one does not exist.
|
|
304
|
+
|
|
305
|
+
**Users of v1.1.1 or earlier**: the old plugin was named `dsh-usage-monitor` or `dsh-quota-monitor`. Check with
|
|
306
|
+
`dsh plugin --profile <profile> list --depth 0`, then remove the old package and install this one so they never run
|
|
307
|
+
together.
|
|
308
|
+
|
|
309
|
+
## Limitations
|
|
310
|
+
|
|
311
|
+
- Only calls that go through the harness are observed; a local Codex CLI login and standalone CLI usage are out of scope.
|
|
312
|
+
- When a supplier does not report a reset time, none is invented; unlimited quotas and unknown balances stay unknown.
|
|
313
|
+
- The trend chart only covers what is stored locally: quota lines depend on samples taken while the plugin runs, so
|
|
314
|
+
history from before it was installed cannot be reconstructed. Quota history is kept for 14 days on disk and the
|
|
315
|
+
displayed window follows the usage retention (7 days by default); with no query in that window there is no point.
|
|
316
|
+
- Local usage and a supplier's bill can differ because of period, time zone and scope.
|
|
317
|
+
- Real balances, paid calls and admin/management-key accounts need to be verified separately with real credentials.
|
|
318
|
+
- The HTTP endpoints target same-origin local access; exposing them through a reverse proxy needs separate work.
|
|
319
|
+
- A corrupt or unsupported usage file is preserved with an error; increments that cannot be written on exit are not
|
|
320
|
+
guaranteed to be saved.
|
|
321
|
+
- A usage-only row has tokens only: no quota, balance or percentage, and it can neither be added nor disabled.
|
|
322
|
+
|
|
323
|
+
## Development
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
npm ci --ignore-scripts
|
|
327
|
+
npm test
|
|
328
|
+
npx playwright install chromium
|
|
329
|
+
npm run test:browser
|
|
330
|
+
npm run test:pack
|
|
331
|
+
npm pack
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
Real-host verification uses a separate data directory and profile and does not touch your daily configuration:
|
|
335
|
+
|
|
336
|
+
```powershell
|
|
337
|
+
npm run test:desktop -- --app 'C:/path/DeepSeek Harness.exe' --package 'C:/path/ds-hu-dsh-token-quota-2.6.0.tgz' --output '.scratch/desktop-v2-check'
|
|
338
|
+
node scripts/verify-web.mjs --app 'C:/path/DeepSeek Harness.exe' --package 'C:/path/ds-hu-dsh-token-quota-2.6.0.tgz' --output '.scratch/web-v2-check'
|
|
339
|
+
npm run test:lifecycle -- --app 'C:/path/DeepSeek Harness.exe' --output '.scratch/lifecycle-v2-check'
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
The output directory must not have been used before. Supplier parsing tests use mocked responses; the real desktop and
|
|
343
|
+
Web checks cover installation, the UI, configuration persistence and rescanning, and do not send chat messages or
|
|
344
|
+
configure real supplier keys.
|
|
345
|
+
|
|
346
|
+
[Windows desktop notes](docs/windows-desktop-adaptation.md) · [Single-panel refactor](docs/single-panel-refactor-execution.md) · [ADR-0002](docs/adr/0002-single-monitor-surface.md) · [v2.5.0 release record](docs/v2.5.0-release-execution.md) · [v2.6.0 release record](docs/v2.6.0-release-execution.md)
|
|
347
|
+
|
|
348
|
+
## Credits
|
|
349
|
+
|
|
350
|
+
This repository is a fork of [shxtmaker/dsh-token-quota](https://github.com/shxtmaker/dsh-token-quota) and is published
|
|
351
|
+
on npm as `@ds-hu/dsh-token-quota`. The plugin id, the settings namespace, the data directory and each supplier's query
|
|
352
|
+
rules come from upstream; behaviour changes are recorded one by one in [CHANGELOG](CHANGELOG.md). Upstream has no npm
|
|
353
|
+
package — use its Releases for the original.
|
|
354
|
+
|
|
355
|
+
## License
|
|
356
|
+
|
|
357
|
+
MIT. The full text is in [LICENSE](LICENSE), which also keeps the copyright notice of the upstream project.
|