@ychris12138/dsh-usage-stats 0.2.10 → 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 CHANGED
@@ -1,5 +1,7 @@
1
1
  # dsh-usage-stats
2
2
 
3
+ <!-- stable-version: 0.3.0 -->
4
+
3
5
  [![GitHub Release](https://img.shields.io/github/v/release/Ychris12138/dsh-usage-stats?display_name=tag&sort=semver&color=1f6feb)](https://github.com/Ychris12138/dsh-usage-stats/releases/latest)
4
6
  [![CI](https://github.com/Ychris12138/dsh-usage-stats/actions/workflows/ci.yml/badge.svg)](https://github.com/Ychris12138/dsh-usage-stats/actions/workflows/ci.yml)
5
7
  [![License](https://img.shields.io/badge/license-MIT-2da44e)](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
- ![dsh-usage-stats v0.2.0 interface preview](docs/images/usage-panel.svg)
13
+ ![dsh-usage-stats interface preview](docs/images/usage-panel.svg)
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
- | 🔄 | 后台监测 | 服务端启动即刷新,之后每五分钟更新全部已配置账户与本地 Token 聚合 |
23
+ | 💰 | 估算费用与预算 | 按事件时间匹配历史价格,提供当前会话、日/月与 session 维度费用;可选日/月预算预警 |
24
+ | 🔄 | 后台监测 | 账户按 active/detail/background 自适应刷新;间隔可配置或完全关闭,本地 Token 聚合保持独立运行 |
22
25
  | 🧩 | 可扩展适配器 | 支持 New API、Sub2API、通用余额模板,以及声明式 JSON Pointer 自定义查询 |
23
- | 🔒 | 本机安全边界 | 五个端点仅接受回环 GET;凭据只在服务端解析并发往校验后的供应商地址 |
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 "github:Ychris12138/dsh-usage-stats"
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`(当前可用)。要启用 GUI「安装」按钮,需先发布:
52
+ **使用前提(重要)**:市场托管安装只接受 npm registry 的精确稳定版本,git 条目仅可浏览。`dsh-usage-stats` 这个 npm 名已被其他项目占用,因此目录条目身份使用 `@ychris12138/dsh-usage-stats`。当前 stable/catalog 版本是 `0.3.0`;每个新版本都按以下顺序发布:
45
53
 
46
- 1. 仓库包身份已统一为 `@ychris12138/dsh-usage-stats`;每次发版需同步 `package.json` / `package-lock.json` / `catalog/v1/plugins.json` 的版本。
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
- > 若最终包名不同,请同步修改 `catalog-source.json` `providerId`/`transport.endpoint``catalog/v1/plugins.json` 的身份字段。发布前目录条目可浏览但安装保持禁用(fail-closed,属预期)。
59
+ > 目录若先指向尚未发布的版本,市场安装会 fail-closed,这是预期行为。只有 npm、Pages catalogDesktop Market 实际安装全部验证后,才算完成发布。
52
60
 
53
61
  升级或卸载:
54
62
 
@@ -110,6 +118,60 @@ npx --yes github:Ychris12138/dsh-usage-stats --no-enable
110
118
 
111
119
  凭据由 Harness 从 `~/.dsh/.credentials.yaml` 解析。安装器不会读取、创建或修改该文件。不要把真实 Key、Cookie 或管理令牌提交到 Git、公开 issue,或粘贴给编码 Agent。
112
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
+
113
175
  ### 余额型供应商
114
176
 
115
177
  DeepSeek、Moonshot 等默认复用对应 provider profile 的 `apiKeyEnv`。例如:
@@ -264,6 +326,16 @@ Passion(provider id 为 `passion` 或域名为 `*.passionapi.com`)会自动
264
326
  3. 使用 `‹` / `›` 切换月份,点击热图日期查看当天的 provider/model 明细。
265
327
  4. 标题栏刷新会更新 Token、provider 列表,并强制刷新当前账户。
266
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
+
267
339
  “最近 14 天”按本地日历计算,只显示窗口内存在用量的日期;未来时间戳不会计入。同一模型来自不同 provider 时会分别统计,例如 `deepseek-official · deepseek-chat` 与 `ark · deepseek-chat`。
268
340
 
269
341
  ## Agent 友好安装 / Agent-friendly installation
@@ -283,12 +355,13 @@ Constraints:
283
355
 
284
356
  Procedure:
285
357
  1. Confirm node, npx, and dsh are available.
286
- 2. Prefer `dsh plugin --profile web update "@ychris12138/dsh-usage-stats"` when already installed; otherwise use `dsh plugin --profile web add "github:Ychris12138/dsh-usage-stats"`.
287
- 3. If unavailable, use: npx --yes github:Ychris12138/dsh-usage-stats
288
- 4. Do not combine bundle installation with an existing manual dsh-usage-stats Cordis entry.
289
- 5. For npx, require a verified package and exactly one Cordis entry, then run again with --check.
290
- 6. Report the installation path and resolved profile paths.
291
- 7. If dsh web is running, report that a restart is needed and stop.
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.
292
365
 
293
366
  Optional account setup (never handle secret values yourself):
294
367
  - OpenRouter account balance requires OPENROUTER_MANAGEMENT_KEY, not the inference key.
@@ -322,14 +395,16 @@ npx --yes github:Ychris12138/dsh-usage-stats --check
322
395
  - 自定义 monitor 默认要求 HTTPS、同源相对路径、手动 redirect 和 JSON 响应,body 上限为 1 MiB。
323
396
  - 发凭据前会筛选域名的 IPv4/IPv6 解析结果并固定一个允许的连接地址,优先使用公网地址;HTTPS 域名解析到 `198.18.0.0/15` 时可作为 Clash/Mihomo 等代理的 synthetic fake-IP 使用。字面量 `198.18/15`、其他私网/特殊地址仍默认拒绝,防止 DNS rebinding 绕过私网限制。
324
397
  - `usageBaseURL` 禁止内嵌 username/password;`Authorization`、`X-API-Key`、`API-Key` 等 header 必须由 credential ref 注入。
325
- - 五个端点仅接受 GET,并同时校验 peer socket 与 Host;支持 IPv4、IPv4-mapped IPv6 和 `[::1]:port`。
398
+ - 九个端点仅接受 GET,并同时校验 peer socket 与 Host;支持 IPv4、IPv4-mapped IPv6 和 `[::1]:port`。
326
399
  - 用量缓存 `~/.dsh/storages/usage-stats-cache.json` 只保存聚合 Token、会话 id、不透明 revision 与折叠游标,不保存提示词、回复或文件路径。
327
400
 
328
401
  本机反向代理会让插件看到代理自身的回环地址。请勿把端点经反向代理暴露到局域网或公网;确需代理时必须在代理层增加可靠认证与访问控制。安全问题请按 [SECURITY.md](SECURITY.md) 私下报告。
329
402
 
330
403
  ## 正确性与数据口径 / Correctness
331
404
 
332
- 统计值来自 `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 完全一致时显示服务端事件级估算。
333
408
 
334
409
  - 活跃会话只处理新追加事件。
335
410
  - 持久化会话使用不透明 revision;未变化时不重复读取日志。
@@ -341,13 +416,17 @@ npx --yes github:Ychris12138/dsh-usage-stats --check
341
416
 
342
417
  | Method | Path | Response |
343
418
  | --- | --- | --- |
344
- | `GET` | `/api/usage-stats/usage` | 按日期/provider/model 聚合的 Token 与缓存命中率 |
419
+ | `GET` | `/api/usage-stats/usage` | 按日期/provider/model 聚合的 Token、派生费用、session 明细与日/月预算状态 |
345
420
  | `GET` | `/api/usage-stats/providers` | provider 列表、account mode、adapter、状态与预警摘要 |
346
421
  | `GET` | `/api/usage-stats/account?provider=<id>` | 当前 provider 的统一余额或 Token Plan 快照;`refresh=1` 强制刷新 |
347
422
  | `GET` | `/api/usage-stats/balance?provider=<id>` | `0.1.x` 余额兼容路由 |
348
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 |
349
428
 
350
- 非 GET 返回 `405`,非回环请求返回 `403`;所有响应均为 JSON 并带 `Cache-Control: no-cache`。
429
+ 非 GET 返回 `405`,非回环请求返回 `403`。API JSON 使用 `Cache-Control: no-cache`;下载响应使用 `Cache-Control: no-store` 与固定文件名。
351
430
 
352
431
  ## 开发与验证 / Development
353
432
 
@@ -355,7 +434,7 @@ npx --yes github:Ychris12138/dsh-usage-stats --check
355
434
  npm install
356
435
  npm run check
357
436
  npm test
358
- npm pack --dry-run
437
+ npm pack --json
359
438
  ```
360
439
 
361
440
  `npm test` 完全离线,覆盖 bundle、客户端渲染与请求竞态、服务端安全边界、余额/Token Plan adapter、缓存和安装器幂等性。真实数据验证需先运行 `dsh web`:
@@ -369,7 +448,7 @@ node scripts/check-balance.mjs
369
448
 
370
449
  ## 兼容性与致谢 / Compatibility & credits
371
450
 
372
- 当前版本为 `0.2.0`。插件依赖 Harness 客户端模块加载器、Cordis 服务与 session persistence;Harness 预发布接口变化时可能需要同步适配。
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 预发布接口变化时可能需要同步适配。
373
452
 
374
453
  - [Javis603/token-monitor](https://github.com/Javis603/token-monitor):参考多 provider 配额归一化与 Z.ai 限额解析。
375
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 five 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.
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.