@ds-hu/dsh-token-quota 2.4.1 → 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 CHANGED
@@ -3,8 +3,66 @@
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
- 更早版本(v2.0.5 及以前)的变更记录在 [README](README.md) 的「vX.Y.Z 更新」小节与
7
- [docs/](docs/) 下的对应执行记录中,本文件自 2.1.0 起逐版本记录。
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` 里的一行。
44
+
45
+ ## [2.5.0] - 2026-11-03
46
+
47
+ ### 变更
48
+
49
+ - **今日行可切区间**:展开明细里的「Today」换成 `[Today ▾]` 选择器,可切「今天 / 近 7 天」;
50
+ token 数、归一比例与下面那条五分量分布条一起换成该区间的合计,图表固定 7 天不跟着变。
51
+ 右侧文字不再重复区间名,只留数量。
52
+ - **新增窗口估算**:同一行右侧给出各窗口(5h / 周 / 月)的 token 估算,可在「剩余」与「套餐总量」
53
+ 之间切换;悬停给出取样区间、分子分母与 ±1pp 区间。
54
+ - **估算按斜率折算**:每 1 个百分点的 token 量 = 取样内本地 token ÷ Δpp,剩余 = 斜率 × 剩余%,
55
+ 总量 = 斜率 × 100%。此前除以累计已用%:月窗口比本地留存长时,分子只拿得到最近几天的 token,
56
+ 3.23B 会推出 3.68B 的总量,而折线显示的是 3.23B 走了约 30pp。
57
+ - 窗口长度由供应商声明(`entries[].windowMs`),宿主把小时桶折成 `estimate{from,to,tokens,dPct}`
58
+ 随 `/state` 下发;取样左端取「窗口起点」与「本地留存边界」的较晚者,两端必须落在同一条折线段上。
59
+ - 文案净增 5 键(158 → 163),测试的文案预算同步上调。
60
+
61
+ ### 修复
62
+
63
+ - **图表柱值数字被折线压花**:柱值标签底下垫一层卡片底色,折线从数字背后穿过,数字不再被压线。
64
+ - **估算显示「—」却无从判断**:门槛从「已用 < 5%」改为「取样 Δpp < 2」——低电平不是噪声源,
65
+ 斜率才是;仍算不出来的窗口悬停提示「本地样本不足」,一个窗口都算不出来时整组不出现。
8
66
 
9
67
  ## [2.4.1] - 2026-11-01
10
68
 
@@ -132,3 +190,50 @@
132
190
  不画一条 0% 的空条。
133
191
  - Token 量级统一 3 位有效数字(`1.32M`、`12.0K`、`999.6K → 1.00M`),不再固定一位小数。
134
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
- 当前供应商集合的今日 Token 用量,按宿主本地日统计。它既不是当前会话用量,也不是全部历史路由的当日总量。峰谷拆分只在 DeepSeek 名下给出,且仍按同一本地日口径逐小时归属。
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
+ [![npm](https://img.shields.io/npm/v/@ds-hu/dsh-token-quota)](https://www.npmjs.com/package/@ds-hu/dsh-token-quota)
4
+ [![verify](https://github.com/ds-hu/dsh-usage-monitor/actions/workflows/verify.yml/badge.svg)](https://github.com/ds-hu/dsh-usage-monitor/actions/workflows/verify.yml)
5
+ [![license](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
6
+ [![DSH](https://img.shields.io/badge/DSH-%E2%89%A5%200.1.7--rc.2-4c6ef5)](#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
+ ![The overview: suppliers with queryable quotas, and one usage-only row](docs/images/overview.png)
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
+ ![Suppliers tab: configure, enable and rescan](docs/images/providers.png)
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.