@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 +37 -0
- package/LICENSE +177 -0
- package/README.md +318 -0
- package/README.zh-CN.md +318 -0
- package/cordis.patch.yml +16 -0
- package/lib/client.js +4074 -0
- package/lib/index.js +1105 -0
- package/lib/provider-quotas.js +526 -0
- package/lib/quota-controls.js +479 -0
- package/package.json +58 -0
- package/screenshots/controls.png +0 -0
- package/screenshots/icon.svg +5 -0
- package/screenshots/quotas.png +0 -0
- package/screenshots/usage.png +0 -0
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&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).
|