@ychris12138/dsh-usage-stats 0.2.9 → 0.3.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/README.md +118 -20
- package/SECURITY.md +3 -1
- package/docs/release-checklist.md +106 -0
- package/docs/release-notes-v0.3.0.md +25 -0
- package/lib/accounts.js +422 -164
- package/lib/balance.js +3 -5
- package/lib/billing.js +319 -0
- package/lib/client.js +626 -70
- package/lib/export.js +227 -0
- package/lib/index.js +435 -63
- package/lib/network.js +65 -0
- package/lib/pricing.js +391 -0
- package/lib/provider-identity.js +126 -0
- package/lib/subscriptions.js +59 -1
- package/lib/usage.js +190 -13
- package/package.json +15 -5
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# dsh-usage-stats
|
|
2
2
|
|
|
3
|
+
<!-- stable-version: 0.3.0 -->
|
|
4
|
+
|
|
3
5
|
[](https://github.com/Ychris12138/dsh-usage-stats/releases/latest)
|
|
4
6
|
[](https://github.com/Ychris12138/dsh-usage-stats/actions/workflows/ci.yml)
|
|
5
7
|
[](LICENSE)
|
|
@@ -8,7 +10,7 @@
|
|
|
8
10
|
|
|
9
11
|
Provider balances, subscription quotas, and token-usage analytics for the DeepSeek Harness Web GUI (`dsh web`).
|
|
10
12
|
|
|
11
|
-

|
|
12
14
|
|
|
13
15
|
> 展示图使用脱敏演示数据;插件不会把 API Key、Cookie、管理 PAT 或上游原始响应发送到浏览器。
|
|
14
16
|
|
|
@@ -18,20 +20,26 @@ Provider balances, subscription quotas, and token-usage analytics for the DeepSe
|
|
|
18
20
|
| --- | --- | --- |
|
|
19
21
|
| 💳 | 统一账户卡片 | API 供应商显示余额,Token Plan 显示分窗口额度;面板一次只呈现当前供应商 |
|
|
20
22
|
| 📊 | Token 用量分析 | 今日、本月、累计、缓存命中率、月历热图,以及按日期/供应商/模型下钻 |
|
|
21
|
-
|
|
|
23
|
+
| 💰 | 估算费用与预算 | 按事件时间匹配历史价格,提供当前会话、日/月与 session 维度费用;可选日/月预算预警 |
|
|
24
|
+
| 🔄 | 后台监测 | 账户按 active/detail/background 自适应刷新;间隔可配置或完全关闭,本地 Token 聚合保持独立运行 |
|
|
22
25
|
| 🧩 | 可扩展适配器 | 支持 New API、Sub2API、通用余额模板,以及声明式 JSON Pointer 自定义查询 |
|
|
23
|
-
|
|
|
26
|
+
| 📦 | 安全导出 | 提供 daily/session CSV 与版本化 JSON;Unicode、CSV 公式前缀和不完整费用均安全处理 |
|
|
27
|
+
| 🔒 | 本机安全边界 | 九个端点仅接受回环 GET;凭据只在服务端解析并发往校验后的供应商地址 |
|
|
24
28
|
|
|
25
|
-
界面支持中文和英文。浏览器只请求当前选择的 provider
|
|
29
|
+
界面支持中文和英文。浏览器只请求当前选择的 provider;账户自动刷新由服务端统一调度。手动刷新会更新用量、供应商列表,并强制刷新当前账户,不会批量强制请求其他供应商。
|
|
26
30
|
|
|
27
31
|
## 快速安装 / Quick start
|
|
28
32
|
|
|
29
33
|
需要 DeepSeek Harness `web` profile(`@deepseek-ai/dsh >= 0.1.0-rc.6`)。
|
|
30
34
|
|
|
35
|
+
稳定版优先安装 npm 上的精确版本;这也是 DSH Desktop Market 使用的同一个包:
|
|
36
|
+
|
|
31
37
|
```bash
|
|
32
|
-
dsh plugin --profile web add "
|
|
38
|
+
dsh plugin --profile web add "@ychris12138/dsh-usage-stats@0.3.0"
|
|
33
39
|
```
|
|
34
40
|
|
|
41
|
+
只有测试尚未发布的 source/RC 时才使用 `dsh plugin --profile web add "github:Ychris12138/dsh-usage-stats"`。GitHub `main` 可能领先 npm stable,不应把 source 安装当作市场安装验收。
|
|
42
|
+
|
|
35
43
|
然后重启已经运行的 `dsh web`,并在浏览器中硬刷新。侧边栏底部会出现“用量/余额”(Usage/Balance)入口。
|
|
36
44
|
|
|
37
45
|
### 插件市场 GUI 安装(DSH Community Market,Path A 标准来源)
|
|
@@ -41,14 +49,14 @@ dsh plugin --profile web add "github:Ychris12138/dsh-usage-stats"
|
|
|
41
49
|
- `catalog/catalog-source.json` — 来源 manifest(`catalog-source.schema.json` v1.0.0)
|
|
42
50
|
- `catalog/v1/plugins.json` — 标准 provider page(`catalog-provider-page.schema.json` v1.0.0)
|
|
43
51
|
|
|
44
|
-
**使用前提(重要)**:市场托管安装只接受 npm registry 的精确稳定版本,git 条目仅可浏览。`dsh-usage-stats` 这个 npm 名已被其他项目占用,因此目录条目身份使用 `@ychris12138/dsh-usage-stats
|
|
52
|
+
**使用前提(重要)**:市场托管安装只接受 npm registry 的精确稳定版本,git 条目仅可浏览。`dsh-usage-stats` 这个 npm 名已被其他项目占用,因此目录条目身份使用 `@ychris12138/dsh-usage-stats`。当前 stable/catalog 版本是 `0.3.0`;每个新版本都按以下顺序发布:
|
|
45
53
|
|
|
46
|
-
1.
|
|
54
|
+
1. 运行 `npm run release:sync -- <version>` 同步 `package.json` / `package-lock.json` / `catalog/v1/plugins.json`,再由 `npm run check:release` 阻止身份或版本漂移。
|
|
47
55
|
2. 发布 scoped 公共包:`npm publish --access public`。
|
|
48
56
|
3. 把 `catalog/v1/plugins.json` 内容发布到 `https://ychris12138.github.io/dsh-usage-stats/v1/plugins`(GitHub Pages,manifest 与 endpoint 必须同源、HTTPS 443、无凭据)。
|
|
49
57
|
4. 在 DSH 插件市场 → 来源管理 → 添加来源,粘贴 manifest URL:`https://ychris12138.github.io/dsh-usage-stats/catalog-source.json`,选择后即可走「可恢复安装边界」GUI 安装。
|
|
50
58
|
|
|
51
|
-
>
|
|
59
|
+
> 目录若先指向尚未发布的版本,市场安装会 fail-closed,这是预期行为。只有 npm、Pages catalog 与 Desktop Market 实际安装全部验证后,才算完成发布。
|
|
52
60
|
|
|
53
61
|
升级或卸载:
|
|
54
62
|
|
|
@@ -98,6 +106,7 @@ npx --yes github:Ychris12138/dsh-usage-stats --no-enable
|
|
|
98
106
|
| Z.ai / 智谱 | 订阅 | `ZAI_API_KEY` | Coding Plan quota/subscription |
|
|
99
107
|
| Kimi For Coding | 订阅 | `KIMI_API_KEY` | `/coding/v1/usages` |
|
|
100
108
|
| MiniMax Coding Plan | 订阅 | `MINIMAX_API_KEY` | `/v1/token_plan/remains` |
|
|
109
|
+
| Ollama 云 | 订阅 | `OLLAMA_API_KEY` | `/api/usage`(5小时 + 周窗口) |
|
|
101
110
|
| New API | 余额 | provider 推理 Token | `/api/usage/token/` |
|
|
102
111
|
| Sub2API / Passion | 自动判别 | provider `apiKeyEnv` | `/v1/usage` |
|
|
103
112
|
| Sub2API 面板(真实) | 余额 | provider 推理 Token | `/user/balance`(复用 apiKey) |
|
|
@@ -109,6 +118,60 @@ npx --yes github:Ychris12138/dsh-usage-stats --no-enable
|
|
|
109
118
|
|
|
110
119
|
凭据由 Harness 从 `~/.dsh/.credentials.yaml` 解析。安装器不会读取、创建或修改该文件。不要把真实 Key、Cookie 或管理令牌提交到 Git、公开 issue,或粘贴给编码 Agent。
|
|
111
120
|
|
|
121
|
+
### 账户刷新 / Account refresh
|
|
122
|
+
|
|
123
|
+
默认刷新间隔是 active 1 分钟、detail 2 分钟、background 15 分钟。严格限流的 New API 或公司中转可以调整全局策略,或完全关闭账户自动刷新:
|
|
124
|
+
|
|
125
|
+
```yaml
|
|
126
|
+
# ~/.dsh/profiles/web/cordis.patch.yml
|
|
127
|
+
- insert:
|
|
128
|
+
- id: usage-stats
|
|
129
|
+
name: "@ychris12138/dsh-usage-stats"
|
|
130
|
+
config:
|
|
131
|
+
refresh:
|
|
132
|
+
enabled: false
|
|
133
|
+
activeMs: 60000
|
|
134
|
+
detailMs: 120000
|
|
135
|
+
backgroundMs: 900000
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
三个间隔必须是 `60000` 至 `86400000` 毫秒之间的整数。需要停止时使用 `refresh.enabled: false`,不要填写超大的 timeout。关闭后,每个相同 provider 配置仍允许首次查询;之后普通面板读取只返回缓存,不会因缓存过期访问上游。账户端点的 `refresh=1`(Retry)仍可显式刷新,provider/monitor 配置变化后也会为新配置重新查询一次。
|
|
139
|
+
|
|
140
|
+
旧配置 `disableBackgroundRefresh: true` 继续等价于 `refresh.enabled: false`;两者同时存在时,显式的 `refresh.enabled` 优先。该开关只关闭账户上游自动刷新,不会关闭本地 Token 用量聚合。
|
|
141
|
+
|
|
142
|
+
### 估算费用与预算 / Estimated cost and budgets
|
|
143
|
+
|
|
144
|
+
预算是可选的非敏感配置,默认关闭。金额只在 provider、model、事件时间与货币均能由内置价格规则可靠确定时计算;未知中转、订阅路线、无价格的 cache write 或混合币种会整体显示 `—`,不会展示部分费用或进行汇率换算。
|
|
145
|
+
|
|
146
|
+
```yaml
|
|
147
|
+
# ~/.dsh/profiles/web/cordis.patch.yml
|
|
148
|
+
- insert:
|
|
149
|
+
- id: usage-stats
|
|
150
|
+
name: "@ychris12138/dsh-usage-stats"
|
|
151
|
+
config:
|
|
152
|
+
budgets:
|
|
153
|
+
currency: USD
|
|
154
|
+
daily: 5
|
|
155
|
+
monthly: 100
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
预算使用本机日历日/月边界:低于 80% 为正常,达到 80% 为 warning,达到 100% 为 critical。`daily` / `monthly` 必须是正数或 `null`;当前版本不做 FX 换算,因此预算货币与可靠价格货币不兼容时状态保持 unknown。
|
|
159
|
+
|
|
160
|
+
### 界面设置 / Display settings
|
|
161
|
+
|
|
162
|
+
Current Session Pill 默认开启。只隐藏 composer 附近的 Pill、保留侧边栏账户面板时:
|
|
163
|
+
|
|
164
|
+
```yaml
|
|
165
|
+
- insert:
|
|
166
|
+
- id: usage-stats
|
|
167
|
+
name: "@ychris12138/dsh-usage-stats"
|
|
168
|
+
config:
|
|
169
|
+
display:
|
|
170
|
+
currentSessionPill: false
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
面板的当前 provider 会保存在浏览器的命名空间 localStorage 中;刷新页面或重启 DSH 后恢复。若该 provider 已被删除,插件会清除旧值并使用原有的 DeepSeek/已配置 provider fallback。该选择不会写入 DSH 设置、服务端缓存或新 API。
|
|
174
|
+
|
|
112
175
|
### 余额型供应商
|
|
113
176
|
|
|
114
177
|
DeepSeek、Moonshot 等默认复用对应 provider profile 的 `apiKeyEnv`。例如:
|
|
@@ -139,10 +202,28 @@ KIMI_API_KEY: your-kimi-key
|
|
|
139
202
|
MINIMAX_API_KEY: your-minimax-key
|
|
140
203
|
# 中国区 MiniMax 用户可选;默认 global
|
|
141
204
|
MINIMAX_API_REGION: cn
|
|
205
|
+
OLLAMA_API_KEY: sk-ollama-your-key
|
|
142
206
|
```
|
|
143
207
|
|
|
144
208
|
OpenCode Go 依次尝试 Harness credential、`~/.local/share/opencode/auth.json`,最后才使用显式 `OPENCODE_GO_AUTH_COOKIE + OPENCODE_GO_WORKSPACE_ID` 兼容回退。Bearer usage endpoint 目前不是公开 API,可能随上游变化;Cookie 等同登录凭据,不应进入日志或 issue。
|
|
145
209
|
|
|
210
|
+
Ollama 云读取 `OLLAMA_API_KEY`,调用 `/api/usage` 展示两个订阅窗口(5 小时会话 + 每周),无余额;`usage` 按 0..1 比例换算为进度条。
|
|
211
|
+
|
|
212
|
+
Ollama 适配器只对**已配置的 provider** 生效,不会自动添加账户:当 provider 的 id 为 `ollama`,或其 baseURL 主机为 `ollama.com`(含子域)时自动选用;本地 Ollama(`localhost:11434`)不会被当作云配额账户。特殊代理/自定义端点可用显式 monitor 绑定:
|
|
213
|
+
|
|
214
|
+
```yaml
|
|
215
|
+
# ~/.dsh/profiles/web/cordis.patch.yml
|
|
216
|
+
- insert:
|
|
217
|
+
- id: usage-stats
|
|
218
|
+
name: dsh-usage-stats
|
|
219
|
+
config:
|
|
220
|
+
monitors:
|
|
221
|
+
relay-ollama: # 你配置的 provider id
|
|
222
|
+
adapter: ollama
|
|
223
|
+
usageBaseURL: https://ollama.example.com
|
|
224
|
+
credentialRef: OLLAMA_API_KEY # 非已配置 provider 时必填
|
|
225
|
+
```
|
|
226
|
+
|
|
146
227
|
Z.ai 全球区使用 `api.z.ai`,中国区使用 `open.bigmodel.cn`。MiniMax 优先使用官方 `www.minimax.io` / `www.minimaxi.com` Token Plan 地址,并解析 5 小时与周窗口的剩余比例和重置时间。
|
|
147
228
|
|
|
148
229
|
### New API、Sub2API 与自定义 monitor
|
|
@@ -245,6 +326,16 @@ Passion(provider id 为 `passion` 或域名为 `*.passionapi.com`)会自动
|
|
|
245
326
|
3. 使用 `‹` / `›` 切换月份,点击热图日期查看当天的 provider/model 明细。
|
|
246
327
|
4. 标题栏刷新会更新 Token、provider 列表,并强制刷新当前账户。
|
|
247
328
|
|
|
329
|
+
### 安全导出 / Secret-free export
|
|
330
|
+
|
|
331
|
+
三个下载端点只导出聚合后的白名单字段,不包含 credential ref/value、Authorization、Cookie、上游原始响应、prompt/reply 或文件路径:
|
|
332
|
+
|
|
333
|
+
- `/api/usage-stats/export/daily.csv`:每天 × provider/model 的四类 Token 与完整费用估算。
|
|
334
|
+
- `/api/usage-stats/export/sessions.csv`:session 标题、provider/model 集合、Token、完整费用估算和最后活动时间。
|
|
335
|
+
- `/api/usage-stats/export.json`:带 `schemaVersion` 的完整聚合数据、公开 pricing provenance、预算和安全账户状态。
|
|
336
|
+
|
|
337
|
+
CSV 使用 UTF-8、RFC 4180 引号与 spreadsheet formula 防护;Unicode 标题可直接打开。费用只在 `costComplete=true` 时导出,未知/混合币种保持空白或 `null`,不会输出部分金额。
|
|
338
|
+
|
|
248
339
|
“最近 14 天”按本地日历计算,只显示窗口内存在用量的日期;未来时间戳不会计入。同一模型来自不同 provider 时会分别统计,例如 `deepseek-official · deepseek-chat` 与 `ark · deepseek-chat`。
|
|
249
340
|
|
|
250
341
|
## Agent 友好安装 / Agent-friendly installation
|
|
@@ -264,12 +355,13 @@ Constraints:
|
|
|
264
355
|
|
|
265
356
|
Procedure:
|
|
266
357
|
1. Confirm node, npx, and dsh are available.
|
|
267
|
-
2. Prefer `dsh plugin --profile web
|
|
268
|
-
3.
|
|
269
|
-
4.
|
|
270
|
-
5.
|
|
271
|
-
6.
|
|
272
|
-
7.
|
|
358
|
+
2. Prefer the exact npm stable used by Desktop Market: `dsh plugin --profile web add "@ychris12138/dsh-usage-stats@0.3.0"` (or update the existing scoped package).
|
|
359
|
+
3. Use `github:Ychris12138/dsh-usage-stats` only when I explicitly ask to test unreleased source/RC code.
|
|
360
|
+
4. If dsh plugin is unavailable, use the compatible source installer only with my approval: `npx --yes github:Ychris12138/dsh-usage-stats`.
|
|
361
|
+
5. Do not combine bundle installation with an existing manual dsh-usage-stats Cordis entry.
|
|
362
|
+
6. For npx, require a verified package and exactly one Cordis entry, then run again with --check.
|
|
363
|
+
7. Report the exact package identity/version, installation path, and resolved profile paths.
|
|
364
|
+
8. If dsh web is running, report that a restart is needed and stop.
|
|
273
365
|
|
|
274
366
|
Optional account setup (never handle secret values yourself):
|
|
275
367
|
- OpenRouter account balance requires OPENROUTER_MANAGEMENT_KEY, not the inference key.
|
|
@@ -303,14 +395,16 @@ npx --yes github:Ychris12138/dsh-usage-stats --check
|
|
|
303
395
|
- 自定义 monitor 默认要求 HTTPS、同源相对路径、手动 redirect 和 JSON 响应,body 上限为 1 MiB。
|
|
304
396
|
- 发凭据前会筛选域名的 IPv4/IPv6 解析结果并固定一个允许的连接地址,优先使用公网地址;HTTPS 域名解析到 `198.18.0.0/15` 时可作为 Clash/Mihomo 等代理的 synthetic fake-IP 使用。字面量 `198.18/15`、其他私网/特殊地址仍默认拒绝,防止 DNS rebinding 绕过私网限制。
|
|
305
397
|
- `usageBaseURL` 禁止内嵌 username/password;`Authorization`、`X-API-Key`、`API-Key` 等 header 必须由 credential ref 注入。
|
|
306
|
-
-
|
|
398
|
+
- 九个端点仅接受 GET,并同时校验 peer socket 与 Host;支持 IPv4、IPv4-mapped IPv6 和 `[::1]:port`。
|
|
307
399
|
- 用量缓存 `~/.dsh/storages/usage-stats-cache.json` 只保存聚合 Token、会话 id、不透明 revision 与折叠游标,不保存提示词、回复或文件路径。
|
|
308
400
|
|
|
309
401
|
本机反向代理会让插件看到代理自身的回环地址。请勿把端点经反向代理暴露到局域网或公网;确需代理时必须在代理层增加可靠认证与访问控制。安全问题请按 [SECURITY.md](SECURITY.md) 私下报告。
|
|
310
402
|
|
|
311
403
|
## 正确性与数据口径 / Correctness
|
|
312
404
|
|
|
313
|
-
统计值来自 `assistant/chunk` 或 `assistant/message` 中 provider-reported `usage`,不是本地估算。相同 turn/step 的后续样本会替换旧样本,并按 `provider/model` 归集。
|
|
405
|
+
Token 统计值来自 `assistant/chunk` 或 `assistant/message` 中 provider-reported `usage`,不是本地估算。相同 turn/step 的后续样本会替换旧样本,并按 `provider/model` 归集。
|
|
406
|
+
|
|
407
|
+
费用是明确标注的估算派生值:每个 usage 样本使用自己的事件时间、原始 provider/model 与四类 token bucket 匹配 `lib/pricing.js`;替换样本会先减去旧费用,再加入新费用。绝不会用“当前价格 × 历史累计 Token”。Current Session Pill 使用 DSH 原生 `tokenUsage` projection 触发重读,并只在 projection 与服务端 session buckets 完全一致时显示服务端事件级估算。
|
|
314
408
|
|
|
315
409
|
- 活跃会话只处理新追加事件。
|
|
316
410
|
- 持久化会话使用不透明 revision;未变化时不重复读取日志。
|
|
@@ -322,13 +416,17 @@ npx --yes github:Ychris12138/dsh-usage-stats --check
|
|
|
322
416
|
|
|
323
417
|
| Method | Path | Response |
|
|
324
418
|
| --- | --- | --- |
|
|
325
|
-
| `GET` | `/api/usage-stats/usage` | 按日期/provider/model 聚合的 Token
|
|
419
|
+
| `GET` | `/api/usage-stats/usage` | 按日期/provider/model 聚合的 Token、派生费用、session 明细与日/月预算状态 |
|
|
326
420
|
| `GET` | `/api/usage-stats/providers` | provider 列表、account mode、adapter、状态与预警摘要 |
|
|
327
421
|
| `GET` | `/api/usage-stats/account?provider=<id>` | 当前 provider 的统一余额或 Token Plan 快照;`refresh=1` 强制刷新 |
|
|
328
422
|
| `GET` | `/api/usage-stats/balance?provider=<id>` | `0.1.x` 余额兼容路由 |
|
|
329
423
|
| `GET` | `/api/usage-stats/subscriptions` | `0.1.x` Token Plan 兼容路由 |
|
|
424
|
+
| `GET` | `/api/usage-stats/session-context?session=<id>` | 当前 live session 的 route/model/account 与同一增量 fold 的 session 费用快照 |
|
|
425
|
+
| `GET` | `/api/usage-stats/export/daily.csv` | secret-free daily provider/model CSV |
|
|
426
|
+
| `GET` | `/api/usage-stats/export/sessions.csv` | secret-free session CSV |
|
|
427
|
+
| `GET` | `/api/usage-stats/export.json` | versioned usage、budget、pricing provenance 与 account-safe JSON |
|
|
330
428
|
|
|
331
|
-
非 GET 返回 `405`,非回环请求返回 `403
|
|
429
|
+
非 GET 返回 `405`,非回环请求返回 `403`。API JSON 使用 `Cache-Control: no-cache`;下载响应使用 `Cache-Control: no-store` 与固定文件名。
|
|
332
430
|
|
|
333
431
|
## 开发与验证 / Development
|
|
334
432
|
|
|
@@ -336,7 +434,7 @@ npx --yes github:Ychris12138/dsh-usage-stats --check
|
|
|
336
434
|
npm install
|
|
337
435
|
npm run check
|
|
338
436
|
npm test
|
|
339
|
-
npm pack --
|
|
437
|
+
npm pack --json
|
|
340
438
|
```
|
|
341
439
|
|
|
342
440
|
`npm test` 完全离线,覆盖 bundle、客户端渲染与请求竞态、服务端安全边界、余额/Token Plan adapter、缓存和安装器幂等性。真实数据验证需先运行 `dsh web`:
|
|
@@ -350,7 +448,7 @@ node scripts/check-balance.mjs
|
|
|
350
448
|
|
|
351
449
|
## 兼容性与致谢 / Compatibility & credits
|
|
352
450
|
|
|
353
|
-
|
|
451
|
+
当前 npm stable 为 `0.3.0`;`v0.3.0` 的完整发布门禁见 [`docs/release-checklist.md`](docs/release-checklist.md),变更摘要见 [`docs/release-notes-v0.3.0.md`](docs/release-notes-v0.3.0.md)。插件依赖 Harness 客户端模块加载器、Cordis 服务与 session persistence;Harness 预发布接口变化时可能需要同步适配。
|
|
354
452
|
|
|
355
453
|
- [Javis603/token-monitor](https://github.com/Javis603/token-monitor):参考多 provider 配额归一化与 Z.ai 限额解析。
|
|
356
454
|
- [xiaoqi20/dsh-opencode-go-usage](https://github.com/xiaoqi20/dsh-opencode-go-usage):参考 DSH 凭据接入、OpenCode `auth.json` 回退与 Bearer usage endpoint。
|
package/SECURITY.md
CHANGED
|
@@ -12,6 +12,8 @@ Never include DeepSeek API keys, credentials files, session contents, raw logs,
|
|
|
12
12
|
|
|
13
13
|
## Scope
|
|
14
14
|
|
|
15
|
-
Security fixes target the latest version on the default branch. The
|
|
15
|
+
Security fixes target the latest version on the default branch. The nine HTTP endpoints are designed for direct loopback use only; exposing them through a reverse proxy is outside the supported security model unless the proxy adds authentication and access control.
|
|
16
|
+
|
|
17
|
+
CSV and JSON exports are fixed, versioned projections of normalized usage and account-safe metadata. They do not serialize plugin/provider configuration, credential references or values, raw upstream responses, prompts, replies, or file paths. CSV text fields are quoted and guarded against spreadsheet-formula execution; incomplete monetary derivations remain blank/null.
|
|
16
18
|
|
|
17
19
|
Declarative account monitors are trusted local configuration, but they still default to HTTPS, same-origin relative paths, manual redirects, JSON-only responses, and a 1 MiB response limit. Before sending credentials, the plugin filters IPv4/IPv6 DNS answers and pins one validated address for the connection. Public addresses are preferred. For HTTPS hostnames only, an IPv4 address in `198.18.0.0/15` may be accepted as a proxy-synthetic fake-IP mapping for Clash/Mihomo-style TUN DNS. Literal targets in that range remain blocked by default, and other private or special-use addresses still require explicit `allowPrivateNetwork` opt-in. Enabling cross-origin, insecure HTTP, or private-network access expands the trust boundary and should be done only for an endpoint you control.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Release checklist
|
|
2
|
+
|
|
3
|
+
This is the release gate for `@ychris12138/dsh-usage-stats`. Completing the checklist prepares a release; it does not authorize npm publishing, tagging, or creating a GitHub Release.
|
|
4
|
+
|
|
5
|
+
## 1. Release candidate baseline
|
|
6
|
+
|
|
7
|
+
- [ ] Start from the reviewed release-candidate PR merged into a clean `main`; record this commit as `RC_BASE_SHA` for provenance only.
|
|
8
|
+
- [ ] Do not publish or tag `RC_BASE_SHA`: the release version has not been committed yet.
|
|
9
|
+
- [ ] Confirm `cordis.patch.yml` quotes `@ychris12138/dsh-usage-stats` and `lib/client.js` registers the same identity through `__ModuleLoader__.load()`.
|
|
10
|
+
- [ ] Confirm the release notes describe estimated costs as estimates and list every unsupported/fail-closed case.
|
|
11
|
+
|
|
12
|
+
## 2. Automated gates
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm ci
|
|
16
|
+
npm run check
|
|
17
|
+
npm test
|
|
18
|
+
npm pack --json
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
- [ ] Inspect the pack manifest: no credentials, local caches, screenshots, backups, review diffs, or untracked planning files.
|
|
22
|
+
- [ ] Install the generated tarball into an isolated DSH profile; do not validate only against the source checkout.
|
|
23
|
+
- [ ] Confirm malformed settings fail before routes or timers register.
|
|
24
|
+
- [ ] Confirm non-GET and non-loopback export/API requests remain rejected.
|
|
25
|
+
|
|
26
|
+
## 3. Fresh install and migration
|
|
27
|
+
|
|
28
|
+
- [ ] Fresh isolated profile: install, restart DSH, hard-refresh the browser, open Usage Stats.
|
|
29
|
+
- [ ] Upgrade an existing v0.2.10 profile without deleting its usage cache or monitor configuration.
|
|
30
|
+
- [ ] Confirm a valid old cache is migrated/refolded and retains exact token totals.
|
|
31
|
+
- [ ] Replace the cache with malformed JSON; confirm the plugin rebuilds from authoritative session events without blocking DSH startup.
|
|
32
|
+
- [ ] Confirm existing account monitors remain compatible and no new provider/monitor is inserted into user configuration.
|
|
33
|
+
- [ ] Confirm `display.currentSessionPill` defaults on and `false` removes the Pill without affecting the sidebar panel.
|
|
34
|
+
- [ ] Confirm a persisted provider selection survives browser refresh and DSH restart; removing that provider clears the saved id and uses the existing fallback.
|
|
35
|
+
|
|
36
|
+
## 4. Export and security
|
|
37
|
+
|
|
38
|
+
- [ ] Download daily CSV, session CSV, and the versioned JSON export.
|
|
39
|
+
- [ ] Check commas, quotes, CR/LF, Unicode titles, and spreadsheet-formula prefixes.
|
|
40
|
+
- [ ] Confirm incomplete/mixed-currency estimates export as blank/null rather than partial amounts.
|
|
41
|
+
- [ ] Search every export for credential names/values, Authorization, cookies, raw URLs with userinfo/query data, prompt text, response text, and file paths.
|
|
42
|
+
- [ ] Confirm exported pricing provenance contains only public rule/source metadata.
|
|
43
|
+
|
|
44
|
+
## 5. Real DSH release-candidate regression
|
|
45
|
+
|
|
46
|
+
- [ ] Test the latest supported `@deepseek-ai/dsh` Desktop/Web release candidate with an isolated profile.
|
|
47
|
+
- [ ] Confirm DSH starts without `Failed to load plugins` or loader identity errors.
|
|
48
|
+
- [ ] Confirm client bundle load, sidebar entry, panel open/close, provider switching, Current Session Pill, cost/budget states, and manual Retry.
|
|
49
|
+
- [ ] Test light and dark themes; confirm a missing composer mount point degrades silently.
|
|
50
|
+
- [ ] With `refresh.enabled: false`, confirm one first account fetch, no expiry-driven upstream requests, manual Retry, and a fresh fetch after provider configuration changes.
|
|
51
|
+
- [ ] Recheck #53 only in an available enterprise proxy environment; record evidence, but do not infer a fix without reproduction.
|
|
52
|
+
- [ ] Recheck #14 with a real MiniMax Coding Plan account: both current and weekly windows plus reset information. Record the sanitized response shape if it fails.
|
|
53
|
+
|
|
54
|
+
## 6. Create the immutable release commit
|
|
55
|
+
|
|
56
|
+
Do not run this section until every release-candidate gate above passes and the maintainer approves preparing the release commit.
|
|
57
|
+
|
|
58
|
+
- [ ] Create a release branch from the reviewed `main` at `RC_BASE_SHA`.
|
|
59
|
+
- [ ] Run `npm run release:sync -- 0.3.0` once to update `package.json`, `package-lock.json`, the Community Market catalog, and documented stable-version references together.
|
|
60
|
+
- [ ] Remove release-candidate wording/status from the v0.3.0 release notes.
|
|
61
|
+
- [ ] Run the release gates again against the synchronized version:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npm run check
|
|
65
|
+
npm test
|
|
66
|
+
npm pack --json
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- [ ] Inspect the final pack manifest, then commit all version/release metadata changes with `chore: prepare v0.3.0 release`.
|
|
70
|
+
- [ ] Record that commit as `RELEASE_SHA`; this replaces `RC_BASE_SHA` as the only publish/tag identity.
|
|
71
|
+
- [ ] Confirm the working tree is clean and `HEAD` equals `RELEASE_SHA`.
|
|
72
|
+
- [ ] Confirm the committed package version, not merely the working-tree version:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
test "$(git show "$RELEASE_SHA:package.json" | jq -r .version)" = "0.3.0"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The release invariant is:
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
npm published source commit
|
|
82
|
+
== v0.3.0 tag commit
|
|
83
|
+
== GitHub Release commit
|
|
84
|
+
== package/catalog version commit
|
|
85
|
+
== RELEASE_SHA
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 7. Publish and market closeout
|
|
89
|
+
|
|
90
|
+
Do not run this section until the immutable release commit exists and the maintainer explicitly authorizes publishing.
|
|
91
|
+
|
|
92
|
+
- [ ] `npm whoami` returns the expected publisher.
|
|
93
|
+
- [ ] From a clean checkout/worktree at exactly `RELEASE_SHA`, run `npm publish --access public --registry=https://registry.npmjs.org/`.
|
|
94
|
+
- [ ] `npm view "@ychris12138/dsh-usage-stats" version --registry=https://registry.npmjs.org/` equals the target version.
|
|
95
|
+
- [ ] Merge or push the release commit to `main` according to the chosen branch workflow; verify `main` contains the exact `RELEASE_SHA` without recreating the release changes.
|
|
96
|
+
- [ ] Only after npm and `main` verification: create the signed/annotated `v0.3.0` tag pointing explicitly to `RELEASE_SHA`.
|
|
97
|
+
- [ ] Verify the tag resolves to the published source commit:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
test "$(git rev-parse v0.3.0^{commit})" = "$RELEASE_SHA"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
- [ ] Create the GitHub Release from `v0.3.0`; verify it resolves to `RELEASE_SHA`.
|
|
104
|
+
- [ ] Verify the public Pages `catalog-source.json` and `/v1/plugins` response content type, package name, and exact version.
|
|
105
|
+
- [ ] Install the exact npm version through DSH Desktop Community Market and restart the host.
|
|
106
|
+
- [ ] Close the npm/market release issue only after the Desktop Market installation succeeds.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# v0.3.0 release notes
|
|
2
|
+
|
|
3
|
+
`v0.3.0` turns dsh-usage-stats from an account/Token dashboard into a route-aware usage and cost observability layer while preserving the v0.2.x credential and loopback security boundaries.
|
|
4
|
+
|
|
5
|
+
## Highlights
|
|
6
|
+
|
|
7
|
+
- A shared provider identity policy keeps route, provider family, account adapter, and pricing eligibility separate. Unknown/custom gateways remain unknown unless explicitly configured.
|
|
8
|
+
- The Current Session Pill shows the active route's account state and event-derived current-session cost beside the composer, and opens the existing provider panel when clicked. It is enabled by default and can be disabled with `display.currentSessionPill: false`.
|
|
9
|
+
- Account health now includes provenance, stale state, last attempt/success, age, bounded diagnostics, configurable refresh intervals, and a true automatic-refresh off switch.
|
|
10
|
+
- DeepSeek historical pricing is matched by exact model, route eligibility, event time, and Shanghai pricing windows. Daily/monthly budgets are optional and fail closed.
|
|
11
|
+
- New API balance display respects the instance's USD/CNY quota settings. Unsupported display types and invalid CNY exchange rates do not masquerade as money.
|
|
12
|
+
- Daily CSV, session CSV, and versioned JSON exports use explicit secret-free projections, preserve Unicode, escape CSV safely, and omit incomplete cost amounts.
|
|
13
|
+
- The account panel remembers its last valid provider in namespaced browser localStorage and falls back safely if that provider is removed.
|
|
14
|
+
- Sidebar footer actions preserve the shared row layout and wrap full-width entries safely, preventing overlap or oversized entries when dsh-usage-stats is installed alongside other footer plugins (#82).
|
|
15
|
+
|
|
16
|
+
## Cost accuracy statement
|
|
17
|
+
|
|
18
|
+
All monetary values are **estimates**, not invoices. A sample is priced only when its provider route is eligible for an official catalog, its model matches exactly, its event timestamp selects a known historical rule, every reported token bucket has a price, and the result has one supported currency. Custom gateways, subscriptions, unknown models, ambiguous historical identity, unpriced cache writes, and mixed currencies return no estimate. The plugin does not call an FX service and does not reinterpret old usage using today's route or price.
|
|
19
|
+
|
|
20
|
+
## Upgrade notes
|
|
21
|
+
|
|
22
|
+
- Existing v0.2.10 configuration remains valid. The new display setting, budgets, and refresh controls are additive and default to the previous behavior.
|
|
23
|
+
- Older usage-cache schemas are invalidated and refolded from authoritative session events. Malformed cache JSON is ignored and rebuilt; it must not block DSH startup.
|
|
24
|
+
- Existing account monitor configuration is normalized without writing credentials or inserting new monitor entries.
|
|
25
|
+
- Browser provider selection is local UI state only; it creates no endpoint and no server-side setting.
|