@sligqoer/dsh-usage-stats 0.2.0 → 0.2.1

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +71 -1
  2. package/NOTICE +39 -0
  3. package/README.en.md +187 -0
  4. package/README.md +93 -263
  5. package/lib/bridge.js +33 -0
  6. package/lib/client.js +2321 -1579
  7. package/lib/index.js +173 -197
  8. package/lib/lm-fingerprint-engine.js +166 -0
  9. package/lib/lm-fingerprint-source.js +134 -0
  10. package/lib/lm-fingerprint-worker.js +31 -0
  11. package/lib/{model-test-history.js → model-detection-history.js} +23 -30
  12. package/lib/model-detection.js +255 -0
  13. package/lib/quota-controls.js +64 -23
  14. package/lib/supplemental-usage.js +77 -0
  15. package/lib/usage-preferences.js +51 -0
  16. package/locale/en.json +6 -0
  17. package/locale/ja.json +6 -0
  18. package/locale/zh.json +6 -0
  19. package/package.json +28 -25
  20. package/screenshots/controls.png +0 -0
  21. package/screenshots/detection.png +0 -0
  22. package/screenshots/quotas.png +0 -0
  23. package/screenshots/usage.png +0 -0
  24. package/third_party/brand-icons/CHANNEL-ICONS-LICENSE +21 -0
  25. package/third_party/brand-icons/LICENSE +59 -0
  26. package/third_party/brand-icons/NOTICE.txt +5 -0
  27. package/third_party/brand-icons/REACT-ICONS-LICENSE +104 -0
  28. package/third_party/brand-icons/channel-icons/LICENSE +21 -0
  29. package/third_party/brand-icons/channel-icons/UPSTREAM.json +6 -0
  30. package/third_party/brand-icons/lobe-icons/LICENSE +21 -0
  31. package/third_party/brand-icons/lobe-icons/UPSTREAM.json +16 -0
  32. package/third_party/brand-icons/react-icons/LICENSE +13 -0
  33. package/third_party/brand-icons/react-icons/UPSTREAM.json +6 -0
  34. package/third_party/lm-fingerprint/LICENSE +21 -0
  35. package/third_party/lm-fingerprint/UPSTREAM.json +32 -0
  36. package/third_party/lm-fingerprint/core/challenge-browser.mjs +210 -0
  37. package/third_party/lm-fingerprint/core/detector-codec.mjs +20 -0
  38. package/third_party/lm-fingerprint/core/fingerprint-core.mjs +121 -0
  39. package/third_party/lm-fingerprint/core/positional.mjs +64 -0
  40. package/third_party/lm-fingerprint/core/shared-detector.mjs +132 -0
  41. package/third_party/lm-fingerprint/data/shared_detector.bin +0 -0
  42. package/third_party/lm-fingerprint/data/unified_bank.json +826820 -0
  43. package/README.zh-CN.md +0 -357
  44. package/lib/fingerprints/KBF-LICENSE.txt +0 -201
  45. package/lib/fingerprints/NOTICE.txt +0 -6
  46. package/lib/fingerprints/kbf-202609.json +0 -1
  47. package/lib/model-capabilities.js +0 -41
  48. package/lib/model-fingerprints.js +0 -146
  49. package/lib/model-match.js +0 -407
  50. package/screenshots/match.png +0 -0
  51. package/screenshots/token-speed.png +0 -0
package/README.md CHANGED
@@ -1,357 +1,187 @@
1
1
  <p align="center">
2
- <img src="screenshots/icon.svg" alt="dsh-usage-stats" width="80" height="80">
2
+ <img src="screenshots/icon.svg" alt="DSH 用量统计" width="80" height="80">
3
3
  </p>
4
4
 
5
5
  <h1 align="center">dsh-usage-stats</h1>
6
6
 
7
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>.
8
+ <strong>在 DSH 里,看清 Token 用量、账户余额与供应商配额。</strong><br>
9
+ 为 <a href="https://github.com/deepseek-ai/deepseek-harness">DeepSeek Harness 桌面端</a>打造的本地用量面板。
10
10
  </p>
11
11
 
12
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>
13
+ <a href="#安装"><img src="https://img.shields.io/badge/DSH-Desktop-2563eb?style=flat-square" alt="DSH 桌面端"></a>
14
+ <a href="https://github.com/Jockjrop/dsh-usage-stats/releases/latest"><img src="https://img.shields.io/badge/release-v0.2.1-64748b?style=flat-square" alt="插件版本 0.2.1"></a>
15
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-22c55e?style=flat-square" alt="Apache 2.0 许可"></a>
16
16
  </p>
17
17
 
18
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>
19
+ <a href="README.en.md">English</a><br>
20
+ <a href="https://github.com/Jockjrop/dsh-usage-stats/releases/latest">下载</a> ·
21
+ <a href="#功能">功能</a> ·
22
+ <a href="#安装">安装</a> ·
23
+ <a href="#使用">使用</a> ·
24
+ <a href="#常见问题">常见问题</a> ·
25
+ <a href="CHANGELOG.md">更新日志</a> ·
26
+ <a href="https://github.com/Jockjrop/dsh-usage-stats/issues">反馈问题</a>
27
27
  </p>
28
28
 
29
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>
30
+ <a href="screenshots/usage.png"><img src="screenshots/usage.png" alt="用量面板:概览指标、今日图表与使用量热力图" width="800"></a>
31
31
  </p>
32
32
 
33
- <p align="center"><sub>Today's usage, lifetime totals, and the patterns behind them. Screenshot versions and values have been edited for this release and use synthetic data.</sub></p>
33
+ <p align="center"><sub>查看今日与累计 Token、小时趋势和使用量热力图。</sub></p>
34
34
 
35
35
  <table align="center">
36
36
  <thead>
37
- <tr><th align="center">Quotas · 配额</th><th align="center">Controls · 控制</th></tr>
37
+ <tr><th align="center">配额</th><th align="center">控制</th></tr>
38
38
  </thead>
39
39
  <tbody>
40
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>
41
+ <td align="center"><a href="screenshots/quotas.png"><img src="screenshots/quotas.png" alt="供应商余额与账号积分" width="400"></a></td>
42
+ <td align="center"><a href="screenshots/controls.png"><img src="screenshots/controls.png" alt="模型功能、展示偏好与查询来源" width="400"></a></td>
43
43
  </tr>
44
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>
45
+ <td align="center">集中查看供应商余额、账号积分和周期额度。</td>
46
+ <td align="center">设置模型功能、展示偏好和自定义配额查询。</td>
47
47
  </tr>
48
48
  </tbody>
49
49
  </table>
50
50
 
51
- <table align="center">
52
- <thead>
53
- <tr><th align="center">Token output speed · token输出速度</th><th align="center">Model match · 模型匹配</th></tr>
54
- </thead>
55
- <tbody>
56
- <tr>
57
- <td align="center"><a href="screenshots/token-speed.png"><img src="screenshots/token-speed.png" alt="Models ranked by TPS with average TTFT" width="400"></a></td>
58
- <td align="center"><a href="screenshots/match.png"><img src="screenshots/match.png" alt="Reference similarity score, audit verdict and collapsed details" width="400"></a></td>
59
- </tr>
60
- <tr>
61
- <td align="center">Compare output speed and first-token wait across providers.</td>
62
- <td align="center">Review the score, verdict and counted audit usage.</td>
63
- </tr>
64
- </tbody>
65
- </table>
66
-
67
- ## Features
68
-
69
- | Tab | What you can do |
70
- | --- | --- |
71
- | **Usage · 用量** | View today's and lifetime tokens, active days, hourly calls, a daily/weekly heatmap, model breakdowns, and token output speed. |
72
- | **Quotas · 配额** | Check configured account balances, subscription windows, and optional WorkBuddy / WorkBuddy AI credits. |
73
- | **Match · 匹配** | Enable Detect model match in Controls to show this tab (off by default). Analyze the current session's request settings and response-declared model; optionally run cancellable independent tests. |
74
- | **Controls · 控制** | Choose a refresh interval, configure custom quota queries, and toggle model details, model matching, token output speed, or the advanced model selector. |
51
+ <p align="center">
52
+ <a href="screenshots/detection.png"><img src="screenshots/detection.png" alt="模型检测:候选排名、库内置信度与采样状态" width="800"></a>
53
+ </p>
75
54
 
76
- - **Follow your usage:** switch the trend between 7 and 30 days, page through daily or weekly history, and compare providers and models.
77
- - **Keep quotas together:** use built-in readers or map a custom provider's JSON response.
78
- - **Refresh on your terms:** fetch manually or enable scheduled queries. Automatic quota refresh is off by default.
79
- - **Inspect overview metrics:** expand the overview for cache hit rate, historical daily token peak, longest completed user round, current and longest usage streaks, and the most-called model in the last seven days. Same model names merge across providers. Round timing requires complete start/end records and excludes idle gaps between messages; today's streak continues through yesterday until a full unused day. Retained historical totals stay included.
80
- - **Compare output speed:** Token output speed is on by default, sorting provider/model pairs by DSH TPS: cumulative output tokens divided by cumulative first-nonempty-output-to-response-completion time, in tok/s. TTFT shows the average time from call start to first non-empty token for completed timed calls, in seconds; missing records show a dash. Samples without valid decode timing are excluded from the ranking. Hide it in Controls.
81
- - **Keep successful results:** failed quota refreshes retain amounts and timestamps with safe diagnostics. Card refreshes query only their provider; query drafts survive tab changes.
82
- - **Choose models faster:** opt into a model/reasoning panel with an effort slider; disabling it restores the official selector.
83
- - **Fit the desktop:** light/dark themes, responsive charts, pinned tabs, and a keyboard-operable provider picker.
84
- - **Follow your language:** Chinese, English, and Japanese UI text updates with DSH's selected language. User-defined names and quota labels stay as configured.
55
+ <p align="center"><sub>查看 LM Fingerprint 候选排名、采样状态和已发生用量。</sub></p>
85
56
 
86
- ## Installation
57
+ ## 功能
87
58
 
88
- **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.
59
+ | 页面 | 你可以做什么 |
60
+ | --- | --- |
61
+ | **用量** | 查看今日与累计 Token、使用天数、小时调用次数、每日/每周热力图、趋势、模型明细与输出速度。 |
62
+ | **配额** | 集中查看供应商余额、账号积分与周期配额,支持手动或定时刷新及自定义查询。 |
63
+ | **检测** | 独立选择供应商和模型,确认预算后运行 LM Fingerprint 检测,查看候选排名、采样状态与历史记录。 |
64
+ | **控制** | 调整展示偏好、配额查询设置、高级模型选择器与逐模型推理强度。 |
89
65
 
90
- ### 1. Open the plugin installer
66
+ - **看清使用趋势**:按日/周浏览热力图,切换 7/30 天趋势,按供应商与模型查看用量。
67
+ - **比较输出速度**:按 TPS 排序,显示平均首 Token 耗时(TTFT);缺少有效时间记录的样本不参与速度排名。
68
+ - **按需刷新配额**:通过 DSH 凭据服务查询已配置供应商,账号配额需要对应的账号插件或宿主服务。自动查询默认关闭。
69
+ - **独立运行检测**:默认采样 3 次,也可选择 1 次初筛;先确认预算,再手动开始,支持取消、超时和用量预算控制。
70
+ - **调整模型设置**:分别控制高级模型选择器与模型推理强度,保留已有的模型属性、参数映射和个人设置。
71
+ - **跟随应用语言**:支持中文、英语和日语,随 DSH 所选语言切换;用户自定义名称与配额标签保持原样。
91
72
 
92
- In DSH Desktop's main sidebar, open **插件 → 添加插件** (Plugins → Add plugin).
73
+ 检测通过随机数样本与参考库对照。排名和库内置信度表示与已知候选的接近程度,不能证明模型身份或能力。读取模型目录、预算和历史结果不会启动推理。
93
74
 
94
- ### 2. Enter the full npm package name
75
+ ## 安装
95
76
 
96
- ```text
97
- @sligqoer/dsh-usage-stats
98
- ```
99
-
100
- Paste it into **包名或地址** (Package name or address) and click **安装** (Install). Keep the full `@sligqoer/` scope.
77
+ 当前插件版本为 **0.2.1**,适配 **DSH Desktop `0.2.1-alpha.2` 和 `0.2.1-rc.2`**。版本不匹配时,宿主插件管理器会拒绝安装或启用。
101
78
 
102
- ### 3. Enable and open
79
+ **推荐通过 DSH Desktop 安装 [npm 包 `@sligqoer/dsh-usage-stats`](https://www.npmjs.com/package/@sligqoer/dsh-usage-stats)。** 已包含预构建模块,无需克隆仓库或在本机构建;通过包名安装后可使用插件页的「检查更新」。
103
80
 
104
- Click **立即启用** (Enable now), then open **Settings → 用量统计**. Restart DSH if its plugin manager asks you to.
81
+ ### 1. 打开插件安装入口
105
82
 
106
- Usage statistics load from your local DSH sessions. Open **配额** and click a refresh button to query an account.
83
+ 在 DSH Desktop 主界面侧栏进入 **插件 → 添加插件**。
107
84
 
108
- <details>
109
- <summary>Install a specific version or a downloaded archive</summary>
110
-
111
- To install version `0.2.0`, enter this in the same installer:
85
+ ### 2. 填入完整 npm 包名
112
86
 
113
87
  ```text
114
- @sligqoer/dsh-usage-stats@0.2.0
88
+ @sligqoer/dsh-usage-stats
115
89
  ```
116
90
 
117
- 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.
91
+ 将包名粘贴到 **包名或地址**,点击 **安装**,保留完整的 `@sligqoer/` 前缀。
118
92
 
119
- ```text
120
- https://github.com/Jockjrop/dsh-usage-stats/releases/latest/download/dsh-usage-stats.tgz
121
- ```
122
-
123
- ```powershell
124
- Get-FileHash ./sligqoer-dsh-usage-stats-0.2.0.tgz -Algorithm SHA256
125
- ```
93
+ ### 3. 启用并打开面板
126
94
 
127
- </details>
95
+ 点击 **立即启用**,进入 **设置 → 用量统计**。插件管理器提示需要重启时,完全退出并重新打开 DSH Desktop。
128
96
 
129
97
  <details>
130
- <summary>Install from source / manually link a checkout</summary>
98
+ <summary>安装指定版本或已下载的压缩包</summary>
131
99
 
132
- For development, install Git, Node.js and pnpm, then build the checkout. This path is verified on Windows with Node.js 24:
100
+ 安装本次版本时,在同一入口填入:
133
101
 
134
- ```sh
135
- git clone https://github.com/Jockjrop/dsh-usage-stats.git
136
- cd dsh-usage-stats
137
- npm ci
138
- npm run build
102
+ ```text
103
+ @sligqoer/dsh-usage-stats@0.2.1
139
104
  ```
140
105
 
141
- Keep the clone in a permanent location; DSH will link to it.
142
-
143
- 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**:
106
+ 也可从 [GitHub 发布页](https://github.com/Jockjrop/dsh-usage-stats/releases/latest)下载 `.tgz` 安装包和 `SHA256SUMS`,校验后填入压缩包的本地绝对路径,无需解压。
144
107
 
145
108
  ```powershell
146
- $pluginDir = (Get-Location).Path.Replace('\', '/')
147
- $dshDataDir = if ($env:DSH_HOME) { $env:DSH_HOME } else { Join-Path $env:USERPROFILE '.dsh' }
148
- $profileDir = Join-Path $dshDataDir 'profiles/desktop'
149
- pnpm --dir $profileDir add "link:$pluginDir"
109
+ Get-FileHash ./sligqoer-dsh-usage-stats-0.2.1.tgz -Algorithm SHA256
150
110
  ```
151
111
 
152
- Open `$profileDir/package.json` and append `"@sligqoer/dsh-usage-stats"` to its existing `dsh.profile.bundles` array. Keep the other bundle entries.
153
-
154
- DSH Desktop manages its own profile; `dsh plugin --profile desktop` is unavailable. After a manual link, start the app and open **Settings → 用量统计**.
112
+ 发布附件包含版本安装包 `sligqoer-dsh-usage-stats-0.2.1.tgz`、通用安装包 `dsh-usage-stats.tgz` 和校验文件 `SHA256SUMS`;两个安装包内容一致。
155
113
 
156
114
  </details>
157
115
 
158
116
  <details>
159
- <summary>Updating or uninstalling</summary>
160
-
161
- **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.
162
-
163
- **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.
117
+ <summary>更新与迁移</summary>
164
118
 
165
- **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.
119
+ 通过 npm 包名安装的用户可在插件页使用「检查更新」。通过 GitHub 地址、压缩包或本地路径安装的用户,需要下载新版重新安装。
166
120
 
167
- **Source installation:** fully exit DSH Desktop, run these commands in the clone, and restart:
168
-
169
- ```sh
170
- git pull --ff-only
171
- npm ci
172
- npm run build
173
- ```
174
-
175
- **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.
121
+ 使用旧包名 `dsh-usage-stats` 的用户,先卸载旧包,再安装 `@sligqoer/dsh-usage-stats`。更新保留本地配置与用量数据;升级记录见 [CHANGELOG.md](CHANGELOG.md)。
176
122
 
177
123
  </details>
178
124
 
179
- ## Usage
125
+ ## 使用
180
126
 
181
- **用量** 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.
127
+ 1. 在「用量」查看概览、趋势、热力图和输出速度;在「控制」调整模型明细与速度的显示。
128
+ 2. 在「配额」点击供应商或账号卡片的刷新按钮。自动查询默认关闭,可在「控制」确认提示后开启。
129
+ 3. 在「检测」选择供应商与模型、设置采样次数和输出上限,确认预算后手动开始。读取目录或历史结果不会启动检测。
130
+ 4. 在「控制」分别开启或关闭高级模型选择器、模型推理强度和模型检测,编辑自定义配额查询。
182
131
 
183
- **配额** shows data returned by connected platforms. Configured balances may show **未查询** until their first query; available cards depend on credentials and account permissions.
132
+ ## 数据与兼容
184
133
 
185
- **控制** lets you change display and refresh settings:
134
+ 本地数据位于 `DSH_HOME/storages`:
186
135
 
187
- | Setting | Default |
136
+ | 文件或目录 | 内容 |
188
137
  | --- | --- |
189
- | Automatic quota refresh | Off |
190
- | Refresh interval | 1 hour; also supports 10 minutes, 5 hours, or daily |
191
- | Model details | On |
192
- | Detect model match | Off |
193
- | Token output speed | On |
194
- | Advanced model selector | Off |
138
+ | `usage-stats-corpus.json` | 会话用量汇总。 |
139
+ | `usage-stats-display.json` | 用量展示偏好。 |
140
+ | `usage-stats-quota-controls.json` | 查询和模型设置、供应商配额缓存。 |
141
+ | `usage-stats-detections.json` | 检测结果与逐次样本用量。 |
142
+ | `usage-stats-lm-fingerprint/` | 通过校验的指纹引擎与参考库更新。 |
143
+ | `usage-stats-supplemental.json` | 按任务和样本 ID 去重的检测用量,重启后保留。 |
195
144
 
196
- 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.
145
+ 普通对话从 DSH 会话日志计数,检测用量按任务和样本 ID 去重后计入统计。请求诊断日志不参与 Token 汇总。更新会保留已保存的配置与历史用量。
197
146
 
198
- <details>
199
- <summary><strong>Supported providers and credentials</strong></summary>
147
+ 从 0.2.0 升级后,模型检测使用 LM Fingerprint,不再提供旧版行为参考、KBF 导入/导出和能力基线测试;已发生的检测用量继续保留。发布安装包不包含个人会话、账号凭据、配额缓存或检测历史。
200
148
 
201
- 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.
149
+ ## 常见问题
202
150
 
203
- The corresponding provider must be configured in DSH. Supported OAuth readers use existing unexpired grants; this plugin does not refresh or modify logins.
151
+ **支持 DSH Web 吗?**
204
152
 
205
- | Optional reader | Host credential references |
206
- | --- | --- |
207
- | OpenRouter account credits | `OPENROUTER_MANAGEMENT_API_KEY` |
208
- | xAI prepaid balance | `XAI_MANAGEMENT_API_KEY`, `XAI_TEAM_ID` |
209
- | Alibaba Cloud Token Plan China | `ALIBABA_CLOUD_ACCESS_KEY_ID`, `ALIBABA_CLOUD_ACCESS_KEY_SECRET`; optional `ALIBABA_CLOUD_SECURITY_TOKEN` |
153
+ 当前版本仅支持 DSH Desktop 的 desktop profile。
210
154
 
211
- 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.
155
+ **为什么配额卡片不显示或无法获取?**
212
156
 
213
- WorkBuddy and WorkBuddy AI require the optional `dsh-workbuddy-connect` adapter. Their quotas are cached and refreshed separately.
157
+ 先确认供应商已配置、凭据可用、账号插件已启用且账户支持对应配额接口。普通模型 API Key 可能没有账单查询权限。
214
158
 
215
- </details>
216
-
217
- <details>
218
- <summary><strong>Set up a custom quota query</strong></summary>
219
-
220
- 1. Open **控制 → 配额查询** and select an existing provider.
221
- 2. Enter the query URL and response mapping.
222
- 3. Click **测试** and check the parsed result.
223
- 4. Confirm the query to show it in **配额**.
224
-
225
- For an endpoint returning `{ "data": { "balance": 12.34 } }`:
226
-
227
- ```json
228
- {
229
- "url": "https://api.example.com/balance",
230
- "method": "GET",
231
- "auth": "provider",
232
- "headers": { "accept": "application/json" },
233
- "response": {
234
- "metrics": [
235
- {
236
- "label": "Account balance",
237
- "kind": "amount",
238
- "remaining": "data.balance",
239
- "currency": "USD"
240
- }
241
- ]
242
- }
243
- }
244
- ```
245
-
246
- 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.
247
-
248
- 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.
249
-
250
- 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.
251
-
252
- </details>
253
-
254
- ## Privacy
255
-
256
- Usage aggregation runs locally. The plugin saves counts, model identifiers, usage timestamps, explicit session titles and working directories, and at most 30 bounded model-evidence records per session. It does not keep conversation bodies, private replay blocks or credentials. Credentials are resolved on the host and are not returned to the renderer. Independent tests persist reported usage and the most recent 10 results without prompts or raw responses.
257
-
258
- The Match tab follows the current session. Metadata declarations provide weak hints only. Reading logs, references and budget previews makes no inference calls.
259
-
260
- Behavioral auditing uses [KBF](https://github.com/Ooo0ption/KBF)-compatible knowledge-boundary fingerprints, including consistent wrong answers. The package includes 28 references and 10,327 probes with dates, deployment provenance and original-file SHA-256 hashes. Some references use third-party deployments; DeepSeek V4.1 Flash uses Novita. Import KBF JSON or create a reference through a trusted configured provider for additional models. Custom calibration filters three consensus passes and performs an independent self-test on the retained set. It does not reproduce the paper's full contrast-model screening experiment.
261
-
262
- Use the reference's CP99 upper error bound and a one-sided binomial test (p < 0.05), with at least 64 valid answers and 80% coverage on both sides. Recalibration is required when the reference's noise bound exceeds 30%. Results indicate significant difference, no significant difference, or insufficient evidence. A p-value is not the probability of model authenticity. Public references use temperature zero and suppressed reasoning; unsupported models need references calibrated with matching parameters. Behavioral changes may reflect versions, prompts or deployment configuration.
263
-
264
- Completed behavioral audits show a 0–100 reference similarity score: matching answers divided by valid answers, multiplied by 100. This is answer agreement, not an authenticity probability. Cancelled, interrupted or insufficient-evidence audits remain unscored. Saved results receive scores without another test. Audit details starts collapsed and contains the parameters, validation process, statistical test and channel measurements.
265
-
266
- Sixteen seeded capability tasks cover code tracing, path reasoning, context retrieval and constraint optimization. Custom references can retain their scores for paired decline tests under matching reasoning settings. Without a capability reference, results describe this run only. TPS/TTFT remain performance measurements.
267
-
268
- Select **Preview test budget** to inspect the actual parameters, call limit, input estimate, output cap and reported-token budget, then **Start audit (uses tokens)**. Quotes expire after five minutes and are single-use. Runs are cancellable with a 60-second per-call timeout; reported-token budgets stop subsequent calls. Reasoning, unreported usage and provider retries follow channel billing, so this is not an absolute invoice cap. Tests do not use conversation content or modify the session; each call's reported usage enters the statistics, including failed or cancelled calls. Store up to 20 private references atomically in `storages/usage-stats-model-baselines.json`; save usage and the last 10 results in `storages/usage-stats-model-tests.json`. A verdict above the form explains behavior, capability decline or an inconclusive result. Host-interrupted tests remain inconclusive. After switching or deleting the original conversation, the previous result stays available and applies only to its listed model and settings.
269
-
270
- Quota tests and refreshes contact the selected platform. There is no analytics or telemetry endpoint.
271
-
272
- <details>
273
- <summary>Storage and request safeguards</summary>
274
-
275
- Local files live under `<DSH_HOME>/storages/`, or the current user's `.dsh/storages/` when `DSH_HOME` is unset:
276
-
277
- | File | Contents |
278
- | --- | --- |
279
- | `usage-stats-corpus.json` | Per-session usage contributions |
280
- | `usage-stats-controls.json` | Controls, custom templates and quota snapshots |
281
- | `usage-stats-model-baselines.json` | Private behavioral and capability references |
282
- | `usage-stats-model-tests.json` | Reported audit usage and the last ten results |
283
-
284
- These are private local files, excluded from Git along with credentials, environment files, databases, logs, backups and previews.
285
-
286
- 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.
287
-
288
- 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.
289
-
290
- </details>
291
-
292
- ## FAQ
293
-
294
- **Does it work in DSH Web?**
295
-
296
- This version loads only in the desktop profile and Electron main window.
297
-
298
- **Why is a quota card missing or unavailable?**
299
-
300
- 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.
159
+ **Token 总数就是账单金额吗?**
301
160
 
302
- **Are displayed token totals a bill?**
161
+ 不是。Token 统计来自本地会话和已上报的检测用量,账户余额与周期额度来自供应商接口。
303
162
 
304
- No. Usage totals sum input, output, cache-read and cache-write tokens. Account balances come from platform APIs.
163
+ **检测排名能证明真实模型身份吗?**
305
164
 
306
- **Will it change DSH's files?**
165
+ 不能。候选排名表示与参考库的接近程度;请求模型不在参考库时,候选仅供比较。
307
166
 
308
- 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.
167
+ ## 接口
309
168
 
310
- ## Contributing
169
+ 宿主服务 `dshUsageStats` 使用 `protocolVersion: 1`,提供 `readStats`、`readControls`、`updateControls`、`readProviderQuotas` 和 `readSupplementalUsage`。
311
170
 
312
- 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.
171
+ HTTP 接口使用 `/api/dsh-usage-stats/*`,提供统计、控制、配额查询与检测功能,仅接受本机与可信来源请求,并禁用缓存。
313
172
 
314
- <details>
315
- <summary><strong>Development and local API</strong></summary>
173
+ ## 开发
316
174
 
317
- 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/`.
175
+ 使用 Node.js 24,并安装 `package-lock.json` 锁定的依赖:
318
176
 
319
177
  ```sh
178
+ npm ci
320
179
  npm run build
321
180
  npm test
322
- node scripts/render-heatmap-check.mjs
323
- node scripts/check-heat-tip-placement.mjs
324
- npm run preview:heatmap
325
- npm pack --dry-run
181
+ npm run check:release
326
182
  npm run release
327
183
  ```
328
184
 
329
- 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`.
330
-
331
- `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).
332
-
333
- 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.
334
-
335
- Routes use the `/api/dsh-usage-stats/` prefix:
336
-
337
- | Route | Method | Purpose |
338
- | --- | --- | --- |
339
- | `stats` | GET | Usage; `days`, `tz`, `model`, optional `fresh=1` |
340
- | `provider-quotas` | GET | Cached quotas; `fresh=1` refreshes |
341
- | `workbuddy`, `workbuddy-ai` | GET | Adapter caches; support `fresh=1` |
342
- | `controls` | GET / POST | Read/update controls; writes require JSON |
343
- | `quota-providers` | GET | Configured providers and credential-free templates |
344
- | `quota-test` | POST | Test a template and return an expiring confirmation ID |
345
- | `model-match` | GET | Existing response hints and the current/previous audit result |
346
- | `model-test` | POST | Preview a budget, start or cancel an audit |
347
- | `model-baselines` | GET / POST | List, import, export or remove behavioral references |
348
-
349
- 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.
350
-
351
- The `platform: "web"` declaration is DSH Desktop's renderer transport; both halves still require the desktop profile and the renderer's native bridge.
352
-
353
- </details>
354
-
355
- ## License
185
+ 修改 `src/` 后运行 `npm run build` 生成 `lib/`。`npm run check:release` 检查版本、构建一致性、第三方完整性与工作区隐私文件;`npm run release` 构建安装包并在独立临时项目中验证安装与加载,输出位于 `release/`。
356
186
 
357
- [Apache-2.0](LICENSE).
187
+ GitHub 发布流程要求标签与包版本一致(本版为 `v0.2.1`),通过检查后使用同一份安装包发布 npm 与 GitHub Release。npm 可信发布对应的工作流文件为 `.github/workflows/release.yml`。第三方资源、来源版本和许可记录于 `third_party/` 与 [NOTICE](NOTICE),本项目使用 [Apache-2.0 许可证](LICENSE)。
package/lib/bridge.js ADDED
@@ -0,0 +1,33 @@
1
+ /** Versioned host-service lookup and registration. */
2
+ export const PROTOCOL_VERSION = 1
3
+ export const HUB_SERVICE = 'dshModelsHub'
4
+ export const USAGE_SERVICE = 'dshUsageStats'
5
+ export const HUB_UPDATED = 'dsh-models-hub/updated'
6
+
7
+ export function getBridge(ctx, name) {
8
+ try {
9
+ const service = ctx.get(name)
10
+ return service?.protocolVersion === PROTOCOL_VERSION ? service : null
11
+ } catch { return null }
12
+ }
13
+
14
+ export function publishBridge(ctx, name, methods) {
15
+ if (getBridge(ctx, name)) throw new Error(`The ${name} service is already registered.`)
16
+ const service = Object.freeze({ protocolVersion: PROTOCOL_VERSION, ...methods })
17
+ if (typeof ctx.provide === 'function') ctx.provide(name, service)
18
+ return service
19
+ }
20
+
21
+ export class IntegrationError extends Error {
22
+ constructor(message = '账号配额暂不可用,请稍后重试。') {
23
+ super(message)
24
+ this.code = 'PLUGIN_UNAVAILABLE'
25
+ this.httpStatus = 503
26
+ }
27
+ }
28
+
29
+ export function requireBridge(ctx, name = HUB_SERVICE) {
30
+ const service = getBridge(ctx, name)
31
+ if (!service) throw new IntegrationError(name === HUB_SERVICE ? undefined : '用量统计暂不可用,请稍后重试。')
32
+ return service
33
+ }