@sligqoer/dsh-usage-stats 0.1.2

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 ADDED
@@ -0,0 +1,37 @@
1
+ # Changelog / 更新日志
2
+
3
+ ## 0.1.2 - 2026-10-01
4
+
5
+ ### 中文
6
+
7
+ - 使用独立的 npm 包名 `@sligqoer/dsh-usage-stats`。通过此包名安装后,插件管理器可从 npm 获取新版本并进行更新。
8
+ - 同步 bundle 与界面模块的包名;构建时从 `package.json` 注入界面模块标识,保留原有用量数据、配额接口和设置标识。
9
+ - 发布脚本支持作用域包的压缩包命名,并验证预构建包的安装、宿主入口和界面入口。
10
+ - GitHub Actions 增加 npm 可信发布流程,使用同一份验证过的压缩包发布 npm 与 GitHub Release;已有版本只在压缩包完整性一致时跳过发布。
11
+ - 更新中英文安装与升级说明:旧版卸载后改用新 npm 包名安装一次,后续使用「检查更新」。保留 GitHub Release 压缩包作为手动安装选项。
12
+
13
+ ### English
14
+
15
+ - Use the dedicated npm package name `@sligqoer/dsh-usage-stats`. Install by this name so the plugin manager can discover and install updates from npm.
16
+ - Align the bundle and renderer module with the scoped package name. Inject the renderer identity from `package.json` while preserving usage data, quota routes, and settings identifiers.
17
+ - Support scoped archive names and verify the prebuilt package's installation, host entry, and renderer entry.
18
+ - Add npm trusted publishing to GitHub Actions. Publish the same verified archive to npm and GitHub Releases, and skip existing npm versions only when archive integrity matches.
19
+ - Update installation and migration instructions in both languages: uninstall the old package once, install the scoped npm package, then use Check updates. Keep Release archives available for manual installation.
20
+
21
+ ## 0.1.1 - 2026-10-01
22
+
23
+ ### 中文
24
+
25
+ - 新增英语、日语界面适配,跟随 DSH 所选语言即时切换,覆盖用量图表、配额、控制设置、模型选择器和提示文案;保留用户自定义名称与标签。
26
+ - 修复反复打开配额页面时卡片消失后重建的闪烁,保留已有数据与 WorkBuddy 套餐展开状态。
27
+ - 刷新期间及部分请求失败时保留最近成功的配额数据,显示失败提示,并防止过期请求覆盖新结果。
28
+ - 顶部版本号改为构建时读取 `package.json`,与插件包版本保持一致。
29
+ - 修复英语界面在窄屏下的图表标题和按钮组横向溢出。
30
+
31
+ ### English
32
+
33
+ - Add English and Japanese UI translations that update with DSH's selected language, including usage charts, quotas, controls, the model selector, and notices. Preserve user-defined names and labels.
34
+ - Fix quota cards disappearing and rebuilding when reopening the quota tab. Keep existing data and expanded WorkBuddy plans.
35
+ - Retain the last successful quota data during refreshes and partial failures, show error notices, and prevent stale requests from overwriting newer results.
36
+ - Read the header version from `package.json` during the build so it matches the plugin package.
37
+ - Fix chart headings and button groups overflowing in the English UI on narrow screens.
package/LICENSE ADDED
@@ -0,0 +1,177 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
package/README.md ADDED
@@ -0,0 +1,318 @@
1
+ <p align="center">
2
+ <img src="screenshots/icon.svg" alt="dsh-usage-stats" width="80" height="80">
3
+ </p>
4
+
5
+ <h1 align="center">dsh-usage-stats</h1>
6
+
7
+ <p align="center">
8
+ <strong>See your token usage, balances, and quotas inside DSH.</strong><br>
9
+ A local usage dashboard for <a href="https://github.com/deepseek-ai/deepseek-harness">DeepSeek Harness Desktop</a>.
10
+ </p>
11
+
12
+ <p align="center">
13
+ <a href="#installation"><img src="https://img.shields.io/badge/DSH-Desktop-2563eb?style=flat-square" alt="DSH Desktop"></a>
14
+ <a href="https://github.com/Jockjrop/dsh-usage-stats/releases/latest"><img src="https://img.shields.io/github/v/release/Jockjrop/dsh-usage-stats?style=flat-square&amp;color=64748b" alt="Latest release"></a>
15
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-22c55e?style=flat-square" alt="Apache 2.0 license"></a>
16
+ </p>
17
+
18
+ <p align="center">
19
+ English · <a href="README.zh-CN.md">简体中文</a><br>
20
+ <a href="https://github.com/Jockjrop/dsh-usage-stats/releases/latest">Download</a> ·
21
+ <a href="#features">Features</a> ·
22
+ <a href="#installation">Installation</a> ·
23
+ <a href="#usage">Usage</a> ·
24
+ <a href="#faq">FAQ</a> ·
25
+ <a href="CHANGELOG.md">Changelog</a> ·
26
+ <a href="https://github.com/Jockjrop/dsh-usage-stats/issues">Feedback</a>
27
+ </p>
28
+
29
+ <p align="center">
30
+ <a href="screenshots/usage.png"><img src="screenshots/usage.png" alt="Usage dashboard with totals, hourly tokens and a calendar heatmap" width="800"></a>
31
+ </p>
32
+
33
+ <p align="center"><sub>Today's usage, lifetime totals, and the patterns behind them.</sub></p>
34
+
35
+ <table align="center">
36
+ <thead>
37
+ <tr><th align="center">Quotas · 配额</th><th align="center">Controls · 控制</th></tr>
38
+ </thead>
39
+ <tbody>
40
+ <tr>
41
+ <td align="center"><a href="screenshots/quotas.png"><img src="screenshots/quotas.png" alt="Provider balances and WorkBuddy credits" width="400"></a></td>
42
+ <td align="center"><a href="screenshots/controls.png"><img src="screenshots/controls.png" alt="Refresh settings and custom quota queries" width="400"></a></td>
43
+ </tr>
44
+ <tr>
45
+ <td align="center">Check provider balances and WorkBuddy credits in one place.</td>
46
+ <td align="center">Set automatic refresh intervals and custom quota queries.</td>
47
+ </tr>
48
+ </tbody>
49
+ </table>
50
+
51
+ ## Features
52
+
53
+ | Tab | What you can do |
54
+ | --- | --- |
55
+ | **Usage · 用量** | View today's and lifetime tokens, active days, hourly calls, a daily/weekly heatmap, and model breakdowns. |
56
+ | **Quotas · 配额** | Check configured account balances, subscription windows, and optional WorkBuddy / WorkBuddy AI credits. |
57
+ | **Controls · 控制** | Choose a refresh interval, configure custom quota queries, and enable model details or the advanced model selector. |
58
+
59
+ - **Follow your usage:** filter historical charts by 7 / 30 / 365 days or all history, and compare providers and models.
60
+ - **Keep quotas together:** use built-in readers or map a custom provider's JSON response.
61
+ - **Refresh on your terms:** fetch manually or enable scheduled queries. Automatic quota refresh is off by default.
62
+ - **Choose models faster:** opt into a model/reasoning panel with an effort slider; disabling it restores the official selector.
63
+ - **Fit the desktop:** light/dark themes, responsive charts, pinned tabs, and a keyboard-operable provider picker.
64
+ - **Follow your language:** Chinese, English, and Japanese UI text updates with DSH's selected language. User-defined names and quota labels stay as configured.
65
+
66
+ ## Installation
67
+
68
+ **Recommended: install the [npm package `@sligqoer/dsh-usage-stats`](https://www.npmjs.com/package/@sligqoer/dsh-usage-stats) through DSH Desktop.** It includes prebuilt modules, needs no Git checkout or local build, and supports the plugin page's Check updates button when installed by package name.
69
+
70
+ ### 1. Open the plugin installer
71
+
72
+ In DSH Desktop's main sidebar, open **插件 → 添加插件** (Plugins → Add plugin).
73
+
74
+ ### 2. Enter the full npm package name
75
+
76
+ ```text
77
+ @sligqoer/dsh-usage-stats
78
+ ```
79
+
80
+ Paste it into **包名或地址** (Package name or address) and click **安装** (Install). Keep the full `@sligqoer/` scope.
81
+
82
+ ### 3. Enable and open
83
+
84
+ Click **立即启用** (Enable now), then open **Settings → 用量统计**. Restart DSH if its plugin manager asks you to.
85
+
86
+ Usage statistics load from your local DSH sessions. Open **配额** and click a refresh button to query an account.
87
+
88
+ <details>
89
+ <summary>Install a specific version or a downloaded archive</summary>
90
+
91
+ To install version `0.1.2`, enter this in the same installer:
92
+
93
+ ```text
94
+ @sligqoer/dsh-usage-stats@0.1.2
95
+ ```
96
+
97
+ You can also manually install a [Release archive](https://github.com/Jockjrop/dsh-usage-stats/releases/latest). Enter the URL below, or download the `.tgz` and `SHA256SUMS`, verify the hash, and enter the archive's local absolute path. Do not extract it before installing.
98
+
99
+ ```text
100
+ https://github.com/Jockjrop/dsh-usage-stats/releases/latest/download/dsh-usage-stats.tgz
101
+ ```
102
+
103
+ ```powershell
104
+ Get-FileHash ./sligqoer-dsh-usage-stats-0.1.2.tgz -Algorithm SHA256
105
+ ```
106
+
107
+ </details>
108
+
109
+ <details>
110
+ <summary>Install from source / manually link a checkout</summary>
111
+
112
+ For development, install Git, Node.js and pnpm, then build the checkout. This path is verified on Windows with Node.js 24:
113
+
114
+ ```sh
115
+ git clone https://github.com/Jockjrop/dsh-usage-stats.git
116
+ cd dsh-usage-stats
117
+ npm ci
118
+ npm run build
119
+ ```
120
+
121
+ Keep the clone in a permanent location; DSH will link to it.
122
+
123
+ In **插件 → 添加插件**, enter the clone's absolute path, install it, and click **立即启用**. To link it manually instead, fully exit DSH Desktop and back up its profile's `package.json`, then run this in **PowerShell from the cloned directory**:
124
+
125
+ ```powershell
126
+ $pluginDir = (Get-Location).Path.Replace('\', '/')
127
+ $dshDataDir = if ($env:DSH_HOME) { $env:DSH_HOME } else { Join-Path $env:USERPROFILE '.dsh' }
128
+ $profileDir = Join-Path $dshDataDir 'profiles/desktop'
129
+ pnpm --dir $profileDir add "link:$pluginDir"
130
+ ```
131
+
132
+ Open `$profileDir/package.json` and append `"@sligqoer/dsh-usage-stats"` to its existing `dsh.profile.bundles` array. Keep the other bundle entries.
133
+
134
+ DSH Desktop manages its own profile; `dsh plugin --profile desktop` is unavailable. After a manual link, start the app and open **Settings → 用量统计**.
135
+
136
+ </details>
137
+
138
+ <details>
139
+ <summary>Updating or uninstalling</summary>
140
+
141
+ **Migrating an older installation:** uninstall the old `dsh-usage-stats` package from the Plugins page, then install and enable `@sligqoer/dsh-usage-stats` by name. This package-name migration is needed only once; the plugin keeps its existing data directory, quota routes, and settings identifiers.
142
+
143
+ **npm installation:** use Check updates on the plugin page and restart if prompted. The current update checker only handles direct npm package-name installations. GitHub URLs, archive URLs, local paths, and `link:` installations need manual updates; “Already up to date” for these sources does not confirm that no newer release exists.
144
+
145
+ **Release installation:** uninstall the package from the Plugins page, install the Release URL above again, and enable it. To uninstall permanently, use the same page's uninstall action.
146
+
147
+ **Source installation:** fully exit DSH Desktop, run these commands in the clone, and restart:
148
+
149
+ ```sh
150
+ git pull --ff-only
151
+ npm ci
152
+ npm run build
153
+ ```
154
+
155
+ **Manual link removal:** exit DSH Desktop, remove only the `@sligqoer/dsh-usage-stats` dependency and bundle entry from its profile, run `pnpm install` there, and restart.
156
+
157
+ </details>
158
+
159
+ ## Usage
160
+
161
+ **用量** shows how much you use and when. Hover a chart or heatmap cell for its breakdown. The overview cards retain their today/lifetime meanings when you change a historical filter.
162
+
163
+ **配额** shows data returned by connected platforms. Configured balances may show **未查询** until their first query; available cards depend on credentials and account permissions.
164
+
165
+ **控制** lets you change display and refresh settings:
166
+
167
+ | Setting | Default |
168
+ | --- | --- |
169
+ | Automatic quota refresh | Off |
170
+ | Refresh interval | 1 hour; also supports 10 minutes, 5 hours, or daily |
171
+ | Model details | On |
172
+ | Advanced model selector | Off |
173
+
174
+ Enabling automatic queries asks you to acknowledge possible query costs. The schedule continues while the settings page is closed. Opening the quota page normally reads cached results.
175
+
176
+ <details>
177
+ <summary><strong>Supported providers and credentials</strong></summary>
178
+
179
+ Built-in readers cover Claude, DeepSeek, StepFun, Codex, GitHub Copilot, OpenRouter, Moonshot China/global, Kimi Coding, MiniMax China/global, Z.AI, GLM Coding, Alibaba Cloud Token Plan China, xAI, and OpenCode Go.
180
+
181
+ The corresponding provider must be configured in DSH. Supported OAuth readers use existing unexpired grants; this plugin does not refresh or modify logins.
182
+
183
+ | Optional reader | Host credential references |
184
+ | --- | --- |
185
+ | OpenRouter account credits | `OPENROUTER_MANAGEMENT_API_KEY` |
186
+ | xAI prepaid balance | `XAI_MANAGEMENT_API_KEY`, `XAI_TEAM_ID` |
187
+ | Alibaba Cloud Token Plan China | `ALIBABA_CLOUD_ACCESS_KEY_ID`, `ALIBABA_CLOUD_ACCESS_KEY_SECRET`; optional `ALIBABA_CLOUD_SECURITY_TOKEN` |
188
+
189
+ OpenCode Go uses only its own configured DSH credential. Zen has no built-in wallet balance reader, but supports custom queries. Alibaba Cloud's international Token Plan is not queried.
190
+
191
+ WorkBuddy and WorkBuddy AI require the optional `dsh-workbuddy-connect` adapter. Their quotas are cached and refreshed separately.
192
+
193
+ </details>
194
+
195
+ <details>
196
+ <summary><strong>Set up a custom quota query</strong></summary>
197
+
198
+ 1. Open **控制 → 配额查询** and select an existing provider.
199
+ 2. Enter the query URL and response mapping.
200
+ 3. Click **测试** and check the parsed result.
201
+ 4. Confirm the query to show it in **配额**.
202
+
203
+ For an endpoint returning `{ "data": { "balance": 12.34 } }`:
204
+
205
+ ```json
206
+ {
207
+ "url": "https://api.example.com/balance",
208
+ "method": "GET",
209
+ "auth": "provider",
210
+ "headers": { "accept": "application/json" },
211
+ "response": {
212
+ "metrics": [
213
+ {
214
+ "label": "Account balance",
215
+ "kind": "amount",
216
+ "remaining": "data.balance",
217
+ "currency": "USD"
218
+ }
219
+ ]
220
+ }
221
+ }
222
+ ```
223
+
224
+ Replace the example URL with the provider's working endpoint. `auth: "provider"` uses its configured DSH credential; authenticated URLs must share the configured or official quota origin.
225
+
226
+ Templates support GET/POST, JSON bodies, amount/window metrics, and paths such as `data.items[0].balance`. Window metrics accept percentage fields or `total` with `remaining`/`used`; `response.rows` selects an array. Use `auth: "none"` for unauthenticated endpoints.
227
+
228
+ Editing invalidates the test; successful tests expire after 15 minutes. A confirmed query overrides the built-in reader for that provider. Removing it restores the built-in reader.
229
+
230
+ </details>
231
+
232
+ ## Privacy
233
+
234
+ Usage aggregation runs locally. The plugin saves counts, model identifiers and usage timestamps, without conversation text. Credentials are resolved on the host and are not returned to the renderer.
235
+
236
+ Quota tests and refreshes contact the selected platform. There is no analytics or telemetry endpoint.
237
+
238
+ <details>
239
+ <summary>Storage and request safeguards</summary>
240
+
241
+ Both files live under `<DSH_HOME>/storages/`, or the current user's `.dsh/storages/` when `DSH_HOME` is unset:
242
+
243
+ | File | Contents |
244
+ | --- | --- |
245
+ | `usage-stats-corpus.json` | Per-session usage contributions |
246
+ | `usage-stats-controls.json` | Controls, custom templates and quota snapshots |
247
+
248
+ These are private local files, excluded from Git along with credentials, environment files, databases, logs, backups and previews.
249
+
250
+ The API checks loopback addresses, Host, Origin and cross-site requests, sends `Cache-Control: no-store`, and hides unexpected host exception details. Another process under your account can access local data.
251
+
252
+ Custom queries reject authentication headers and common credential fields in templates, require the appropriate origin for provider authentication, and do not follow redirects. They have an 8-second timeout and a 1 MB response limit. WorkBuddy adapters retain quota display fields only.
253
+
254
+ </details>
255
+
256
+ ## FAQ
257
+
258
+ **Does it work in DSH Web?**
259
+
260
+ This version loads only in the desktop profile and Electron main window.
261
+
262
+ **Why is a quota card missing or unavailable?**
263
+
264
+ Check that the provider is configured, its credential is usable, and the account supports the quota API. A model API key may not have billing permissions.
265
+
266
+ **Are displayed token totals a bill?**
267
+
268
+ No. Usage totals sum input, output, cache-read and cache-write tokens. Account balances come from platform APIs.
269
+
270
+ **Will it change DSH's files?**
271
+
272
+ It registers an external bundle. The optional model selector takes over a UI slot while enabled; disabling it restores the official selector without changing DSH source files.
273
+
274
+ ## Contributing
275
+
276
+ Bug reports and pull requests are welcome. For a bug, include your DSH version, plugin version, steps to reproduce, and a screenshot with private account details removed.
277
+
278
+ <details>
279
+ <summary><strong>Development and local API</strong></summary>
280
+
281
+ Edit module sources in `src/`. `npm run build` synchronizes modules to `lib/` and root compatibility copies and injects the renderer package identity and header version from `package.json`; package exports load `lib/`.
282
+
283
+ ```sh
284
+ npm run build
285
+ npm test
286
+ node scripts/render-heatmap-check.mjs
287
+ node scripts/check-heat-tip-placement.mjs
288
+ npm run preview:heatmap
289
+ npm pack --dry-run
290
+ npm run release
291
+ ```
292
+
293
+ Tests use synthetic data and temporary DSH homes; no live credentials or paid calls are required. Set `DSH_THEME_CLIENT` to validate an installed theme client instead of the checked-in alias contract. The synthetic preview writes an ignored `preview-heatmap.html`.
294
+
295
+ `npm run release` builds the package, writes `sligqoer-dsh-usage-stats-<version>.tgz`, the `dsh-usage-stats.tgz` alias and `SHA256SUMS` to the ignored `release/` directory, then verifies installation in a temporary profile. Release notes include the matching version entry from [CHANGELOG.md](CHANGELOG.md).
296
+
297
+ A matching `v<package.json version>` tag triggers GitHub Actions to run the tests, publish the verified archive as a public npm package through trusted publishing, and attach the same files to a GitHub Release. Trust is bound to the `release.yml` workflow in `Jockjrop/dsh-usage-stats`; no npm token is stored in the repository. `npm run publish:release` publishes the prebuilt archive and skips an existing version only when its integrity matches; different contents fail the release.
298
+
299
+ Routes use the `/api/dsh-usage-stats/` prefix:
300
+
301
+ | Route | Method | Purpose |
302
+ | --- | --- | --- |
303
+ | `stats` | GET | Usage; `days`, `tz`, `model`, optional `fresh=1` |
304
+ | `provider-quotas` | GET | Cached quotas; `fresh=1` refreshes |
305
+ | `workbuddy`, `workbuddy-ai` | GET | Adapter caches; support `fresh=1` |
306
+ | `controls` | GET / POST | Read/update controls; writes require JSON |
307
+ | `quota-providers` | GET | Configured providers and credential-free templates |
308
+ | `quota-test` | POST | Test a template and return an expiring confirmation ID |
309
+
310
+ The corpus refreshes every 30 seconds. Requests wait up to 1500 ms and may return `stale: true`/`partial: true`. SQLite fingerprints require `node:sqlite`; otherwise sessions are reread. Timezone changes re-bucket stored events, with possible approximation for old hourly-only history at fractional-hour boundaries.
311
+
312
+ The `platform: "web"` declaration is DSH Desktop's renderer transport; both halves still require the desktop profile and the renderer's native bridge.
313
+
314
+ </details>
315
+
316
+ ## License
317
+
318
+ [Apache-2.0](LICENSE).