@feiyang666/dsh-usage-plugin 1.11.1 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,308 +1,311 @@
1
- <div align="center">
2
-
3
- # DeepSeek Harness Usage & Cost Tracker (dsh-usage-plugin)
4
-
5
- **English** · [简体中文](./README.zh.md)
6
-
7
- [GitHub](https://github.com/feiyang-dev/dsh-usage-plugin) · [npm](https://www.npmjs.com/package/@feiyang666/dsh-usage-plugin) · MIT License
8
-
9
- **A community plugin for DeepSeek Harness** — records token usage and cost for every model call, with peak/off-peak billing, balance query, a calendar heatmap, and CSV / JSON / PNG export.
10
-
11
- ![License](https://img.shields.io/badge/license-MIT-blue.svg)
12
- ![Node](https://img.shields.io/badge/node-%3E%3D18-339933)
13
- ![Platform](https://img.shields.io/badge/platform-web%20%26%20desktop-4d9fff)
14
-
15
- </div>
16
-
17
- ---
18
-
19
- > ## 🔔 Important Notice (2026-08-16): npm package renamed
20
- >
21
- > The **npm package has been renamed from `@feiyang666/deepseekharnessdesktop` to `@feiyang666/dsh-usage-plugin`** (matching the GitHub repo `feiyang-dev/dsh-usage-plugin`).
22
- >
23
- > - Use the new package name for install / upgrade: `dsh plugin --profile web add @feiyang666/dsh-usage-plugin`
24
- > - The old package `@feiyang666/deepseekharnessdesktop` remains published for a while, but it is **no longer maintained and will not receive updates** — please migrate soon.
25
- > - The desktop client ([`DeepSeek Harness Desktop`](https://github.com/feiyang-dev/DeepSeek-Harness-Desktop)) supports both package names and will auto-detect old-name installs with a **one-click update** to the new name.
26
-
27
- ---
28
-
29
- ## Overview
30
-
31
- dsh-usage-plugin is a **usage & cost tracker** plugin in the DeepSeek Harness ecosystem (a DSH plugin shipped as a Host + Client two-in-one package). After installation, **"Usage & Cost"** and **"Balance Query"** tabs appear in the Web UI, right after "Conversation" and "Trace":
32
-
33
- > Supports **Windows / macOS / Linux**: paths are handled per platform (`node:path`), and the folder picker / "reveal in file manager" use each OS's native mechanism (macOS: `osascript` / `open`; Linux: `zenity` / `xdg-open`). Balance query and export do not depend on Windows-only commands.
34
-
35
- - **Usage & Cost**: records each model call's token usage and cache hits (input miss / cache hit / cache write / output / reasoning / finish reason), and computes cost using DeepSeek's peak/valley or base pricing (peak hours on weekdays are automatically priced by Beijing time 09:00–12:00 and 14:00–18:00; since 2026-08-23 weekends are billed entirely at the off-peak rate). Model names come from the actual request parameters, so non-DeepSeek models are shown truthfully instead of "unknown model"; models without an official price are counted as 0. The overview shows a by-model table plus a by-API-provider × model drill-down (each provider grouped with every model's calls and peak/off-peak cost split) and a grand total row. The overview also supports **date filtering** (Today / Last 7 days / Last 30 days / All, plus a custom start–end range), so the aggregate stats can be scoped to any single day or date range.
36
- - **Usage Calendar**: a monthly daily-usage heatmap (colored by cost or call count), hover for details including the peak/off-peak cost split, click a day for its call list and peak/off-peak totals, plus a per-day statistics table with peak cost / off-peak cost / total columns and monthly rollups.
37
- - **Cache Hit List**: newest-first, fully scrollable, with quick filters (Today / 7 days / 30 days / All) and custom date ranges; the summary line and footer total split peak vs off-peak consumption with a grand cost total. The list is paginated (100 rows per page), so it stays smooth even with large data volumes.
38
- - **Price Table**: the official DeepSeek API price table (covering `deepseek-v4-flash` / `deepseek-v4-flash-vision-exp` / `deepseek-v4-pro`) — base and peak/valley unit prices shown side by side (peak vs off-peak), editable in-panel and persisted to `pricing.json`, with a reset-to-default option.
39
- - **Balance Query**: queries your DeepSeek account balance using the configured `DEEPSEEK_API_KEY`.
40
- - **Export**: CSV / JSON / **PNG long image** (newest-first, up to the latest 2000 records, warns if exceeded; the PNG report includes peak/off-peak cost columns), to any directory (native picker), auto-opens the folder after export.
41
- - **Import**: merge-imports JSON / CSV files, deduplicated by time.
42
- - **Persistence**: records are written live to `<session workspace>/dsh-usage/usage-records.json` and restored on restart (cap 100000 records).
43
- - **UI adaptation**: panel typography scales with the app's display-size setting (em-relative fonts); table wrapping and spacing are tuned so large display sizes stay readable.
44
-
45
- ---
46
-
47
- ## Screenshots
48
-
49
- ### Usage & Consumption
50
- ![Usage & Consumption](./docs/assets/usage-overview.png)
51
-
52
- ### Balance Query
53
- ![Balance Query](./docs/assets/balance-query.png)
54
-
55
- ## Recommended Installation
56
-
57
- > Either method works and is equivalent. **We recommend the desktop app** — fully graphical, no command line needed.
58
-
59
- ### Option 1 (recommended): One-click via the desktop app
60
-
61
- Install [DeepSeek Harness Desktop](https://github.com/feiyang-dev/DeepSeek-Harness-Desktop), open it, then go to **"Install Plugins" → Recommended → Usage & Cost Tracker → Install** and click **"Restart Service Now"** to activate.
62
-
63
- ### Option 2: Command line
64
-
65
- ```bash
66
- # Prerequisite: install dsh (npm install -g @deepseek-ai/dsh)
67
- dsh plugin --profile web add @feiyang666/dsh-usage-plugin
68
- ```
69
-
70
- Or install to another profile:
71
-
72
- ```bash
73
- dsh plugin --profile web add @feiyang666/dsh-usage-plugin
74
- dsh plugin --profile headless add @feiyang666/dsh-usage-plugin
75
- ```
76
-
77
- Restart the dsh web service after installation. Detailed manual install / wiring / uninstall / troubleshooting follows below.
78
-
79
- ---
80
-
81
- ## What's in the package
82
-
83
- One npm package = a **host half** (Node-side Cordis plugin: recording, billing, balance query, export — see `lib/index.js`) + a **client half** (browser-side panel — see `lib/client.js`, which talks to the host via `/usage/api`).
84
-
85
- The package integrates with DSH through two declarations:
86
-
87
- | Declaration | Purpose |
88
- | --- | --- |
89
- | `dsh.bundle.patch` (`cordis.patch.yml`) | Lets DSH recognize it as a **standard bundle plugin package**: `dsh plugin --profile <name> add <package>` installs and wires it in one command, no manual config editing |
90
- | `dsh.client` + `exports["./client"]` | Lets the web client auto-load the browser panel at `/plugins/<package>/client.js` |
91
-
92
- So for users, **installation is one command** — no YAML editing, no manual file copying.
93
-
94
- ---
95
-
96
- ## Installation (for users)
97
-
98
- ### 0. Prerequisites
99
-
100
- - DeepSeek Harness installed (`npm install -g @deepseek-ai/dsh`, or a desktop app built on it, or `npx @deepseek-ai/dsh web`).
101
- - Option A (recommended) needs **pnpm**: `npm install -g pnpm` (or `corepack enable`).
102
- - Make sure `dsh` is on PATH (for the desktop app, run in its bundled terminal).
103
-
104
- ### 1. Method A (recommended): one command
105
-
106
- ```bash
107
- dsh plugin --profile web add @feiyang666/dsh-usage-plugin
108
- ```
109
-
110
- This does three things (all automatic):
111
-
112
- 1. Installs the package via pnpm into `~/.dsh/profiles/web` (auto-initializes the profile on first use);
113
- 2. Detects the package's `dsh.bundle` declaration and writes the package name into the profile's `dsh.profile.bundles` layer list;
114
- 3. After restart, DSH reads the package's `cordis.patch.yml` and mounts the plugin row into the app tree **no manual config editing**.
115
-
116
- Same for other profiles (replace `web` with your profile name, e.g. `dsh plugin --profile headless add ...`; `dsh web` equals `dsh --profile web`).
117
-
118
- > Test a local tarball: `dsh plugin --profile web add C:\path\to\feiyang666-dsh-usage-plugin-1.9.0.tgz`
119
-
120
- ### 2. Method B: manual install (no pnpm / no `dsh plugin`)
121
-
122
- Only for when you have no pnpm or want full manual control. **Do not `npm install` directly at `~/.dsh/profiles`** (that dir has no package.json; npm would treat the whole node_modules as residue and wipe it).
123
-
124
- **B1. Use pnpm but not `dsh plugin`:**
125
-
126
- ```bash
127
- cd ~/.dsh/profiles/web
128
- pnpm add @feiyang666/dsh-usage-plugin
129
- # then manually append the plugin row to web/cordis.patch.yml (see B3) and restart
130
- ```
131
-
132
- **B2. Or use npm:** add a minimal package.json to the profile first, then install:
133
-
134
- ```bash
135
- cd ~/.dsh/profiles/web
136
- # if no package.json exists there yet (only after `dsh plugin` init):
137
- # echo '{"name":"dsh-profile-web","private":true,"dependencies":{}}' > package.json
138
- npm install @feiyang666/dsh-usage-plugin
139
- ```
140
-
141
- **B3. Wire it up (once, idempotent):** append to `~/.dsh/profiles/web/cordis.patch.yml`:
142
-
143
- ```yaml
144
- - insert:
145
- - id: usage-plugin
146
- name: '@feiyang666/dsh-usage-plugin'
147
- inject:
148
- - fs
149
- - webServer
150
- - subprocess
151
- - credentials
152
- - sandboxPolicy
153
- - agents
154
- ```
155
-
156
- Or just run the package's built-in wiring script (auto-finds the profile and appends, idempotent):
157
-
158
- ```bash
159
- node node_modules/@feiyang666/dsh-usage-plugin/scripts/wire.js
160
- ```
161
-
162
- > ⚠️ The `inject` list is **required**: it makes Cordis wait until `fs` / `webServer` / `subprocess` / `credentials` / `sandboxPolicy` / `agents` are ready before activating the plugin. Without it the `/usage/api` route never registers and the panel fails with `Unexpected end of JSON input`.
163
-
164
- ### 3. Method C: desktop app
165
-
166
- The desktop app (e.g. [DeepSeek Harness Desktop](https://github.com/feiyang-dev/DeepSeek-Harness-Desktop)) uses the same `~/.dsh/profiles` underneath. Run Method A's command in any terminal, restart the app, and the plugin activates automatically (the app starts the same `dsh web`).
167
-
168
- ### 4. Restart and verify
169
-
170
- Restart the DeepSeek Harness web app (command line: kill the old process and re-run `dsh web`; desktop: fully quit and reopen). Then:
171
-
172
- - Refresh http://127.0.0.1:3080 — after "Conversation" and "Trace", you should see **"Usage & Cost"** and **"Balance Query"** tabs; there are entries in Settings too.
173
- - The "Usage & Cost" panel contains **Overview / Usage Calendar / Cache Hit List / Price Table** subtabs.
174
- - Send a message and the "Usage & Cost" panel should show this call's token / cost record.
175
-
176
- ### 5. Configuration (for balance query)
177
-
178
- "Balance Query" uses the configured `DEEPSEEK_API_KEY`: set the API Key in **Settings → Models** (same key used for chats), then open the "Balance Query" tab and click "Query Balance".
179
-
180
- ---
181
-
182
- ## Uninstall
183
-
184
- ```bash
185
- dsh plugin --profile web remove @feiyang666/dsh-usage-plugin
186
- ```
187
-
188
- (Equivalent to pnpm remove; `dsh plugin` auto-removes the package name from the `dsh.profile.bundles` layer list.) Restart the app afterward.
189
-
190
- For manual installs (Method B), do it in reverse: remove the `usage-plugin` row from `cordis.patch.yml`, then `pnpm remove` / `npm uninstall` the package, and restart.
191
-
192
- > Upgrading from a 1.0.x manual-wiring install to 1.1.x: first remove the old `usage-plugin` row from `cordis.patch.yml` (or follow the uninstall flow), then reinstall via Method A to avoid mounting the plugin twice.
193
-
194
- ---
195
-
196
- ## How to update
197
-
198
- Releasing happens on npm, so updating just means pulling the latest published package. Your usage history is **safe** — since v1.9.2 it lives in a fixed dedicated directory (not in any profile / workspace), so an update never wipes it.
199
-
200
- ### Desktop app
201
- Open **"Install Plugins"** → find **Usage & Cost Tracker** → click **Update** (or **Re-install**) → **"Restart Service Now"**. If there is no Update button, just remove then re-add it.
202
-
203
- ### Command line (Method A)
204
- Re-running `add` is idempotent and pulls the newest version:
205
-
206
- ```bash
207
- dsh plugin --profile web add @feiyang666/dsh-usage-plugin
208
- dsh web # restart
209
- ```
210
-
211
- Pin a specific version:
212
-
213
- ```bash
214
- dsh plugin --profile web add @feiyang666/dsh-usage-plugin@1.9.3
215
- ```
216
-
217
- ### Manual install (Method B)
218
- In the profile dir:
219
-
220
- ```bash
221
- cd ~/.dsh/profiles/web
222
- pnpm update @feiyang666/dsh-usage-plugin # or: npm update @feiyang666/dsh-usage-plugin
223
- ```
224
-
225
- ### Verify the installed version
226
- ```bash
227
- npm ls @feiyang666/dsh-usage-plugin --prefix ~/.dsh/profiles/web
228
- ```
229
-
230
- > ⚠️ **Do not hand-edit files under `~/.dsh/profiles/web/node_modules/@feiyang666/dsh-usage-plugin/`** (e.g. `lib/index.js` / `lib/client.js`). Every update re-extracts the package from npm and overwrites those files, so local edits are silently lost. To change behavior, fork the repo and publish your own version, or contribute upstream.
231
-
232
- ---
233
-
234
- ## Data & locations
235
-
236
- > **Since v1.9.2**, records are stored in a **fixed, dedicated data directory** (fixes [#4](https://github.com/feiyang-dev/dsh-usage-plugin/issues/4)). The path no longer follows the session workspace / `~/.dsh` / desktop-app install dir, so your history never "disappears" (counted as 0) when the workspace changes, and the path shown in the UI equals the on-disk path.
237
-
238
- - **Records**: `<data root>/dsh-usage/usage-records.json`
239
- - Resolution order for the **data root** (data always lands in the **first writable** dir of this list, **never in the workspace** unless all of the below are unwritable):
240
- 1. env var `DSH_USAGE_DATA_DIR` (if set) overrides everything;
241
- 2. Windows: `%LOCALAPPDATA%\dsh-usage-plugin` (falls back to `%APPDATA%` if `LOCALAPPDATA` is unset);
242
- 3. user home dir: `~/dsh-usage-data` (Windows `%USERPROFILE%\dsh-usage-data`, macOS/Linux `~/dsh-usage-data`);
243
- 4. **fallback (rare)**: current workspace `<workspace>/dsh-usage` only used when all system/user dirs above are unwritable, and the panel will show a "persistence disabled" warning.
244
- - **Writes bypass the model sandbox**: persistence is done by the host plugin process's own filesystem, not subject to the `workspace-write` sandbox, so the fixed directory is always writable and data is not lost when switching workspaces.
245
- - Default on Windows: `%LOCALAPPDATA%\dsh-usage-plugin\dsh-usage\usage-records.json`
246
- - **Legacy data auto-merge**: on first start, records previously scattered in `%USERPROFILE%\dsh-usage`, `~/.dsh/dsh-usage`, and each workspace's `dsh-usage` (or `.dsh-usage-records.json`) are merged into the fixed root, deduplicated by `time` — no manual migration needed.
247
- - Price config (edited & saved in the panel): `<data root>/dsh-usage/pricing.json`
248
- - Default export dir: `<data root>/dsh-usage/{csv,json,images}/`
249
- - Custom export dir: set in the panel's "Export target directory" or click "Choose directory…"
250
- - Startup diagnostics (if the plugin fails to activate): `dsh-usage-boot.log` next to the data root
251
-
252
- ---
253
-
254
- ## FAQ
255
-
256
- | Symptom | Cause / Fix |
257
- | --- | --- |
258
- | Panel reports `Unexpected end of JSON input` | The plugin row is missing the `inject` list, so the route isn't registered. Add the inject list per Method B3 and restart |
259
- | Panel blank / no top tab | Plugin not activated. Check `dsh-usage-boot.log`; confirm the `cordis.patch.yml` row exists with the correct `name` |
260
- | Balance query fails with "DEEPSEEK_API_KEY not configured" | Set the API Key in Settings Models |
261
- | Balance query network error | Ensure `api.deepseek.com` is reachable (configure a proxy if needed) |
262
- | `dsh plugin` reports pnpm not found | Install pnpm: `npm install -g pnpm` |
263
- | Install can't reach the npm registry | Set a mirror: `npm config set registry https://registry.npmmirror.com` (or `pnpm config set registry ...`) and retry |
264
- | After uninstall, still reports `Cannot find package '@feiyang666/...'` | A package reference remains in the profile. Remove the corresponding row from `cordis.patch.yml` and the package name from `dsh.profile.bundles`, then restart |
265
-
266
- ---
267
-
268
- ## Related Projects
269
-
270
- | Project | Description | Installation |
271
- | --- | --- | --- |
272
- | [DeepSeek Harness Desktop](https://github.com/feiyang-dev/DeepSeek-Harness-Desktop) | Windows desktop console: install/start/stop/restart the dsh web service with one click, built-in plugin management — **install this plugin from its Recommended section** | Download the desktop app and click a few buttons |
273
- | [Data Vault (dsh-vault)](https://github.com/feiyang-dev/dsh-vault) | Auto backup / wipe detection / one-click restoreprotects chat history and workspace data | One-click from the desktop app, or `dsh plugin add @feiyang666/dsh-vault` |
274
- | [DeepSeek-Harness](https://github.com/deepseek-ai/DeepSeek-Harness) | Official CLI / Web service | Quick start below |
275
-
276
- ### Running DeepSeek Harness
277
-
278
- **Quick start (via npm)**
279
-
280
- Install Node.js, then run:
281
-
282
- ```bash
283
- npx @deepseek-ai/dsh web
284
- ```
285
-
286
- This command starts the Web UI at the default address http://127.0.0.1:3080. See the [Web UI Guide](https://github.com/deepseek-ai/DeepSeek-Harness) for details.
287
-
288
- **Run from source**
289
-
290
- To run from the repository source:
291
-
292
- ```bash
293
- git clone https://github.com/deepseek-ai/deepseek-harness.git
294
- cd deepseek-harness
295
- pnpm install
296
- pnpm run build
297
- pnpm dsh web
298
- ```
299
-
300
- ## Acknowledgements
301
-
302
- - **[@Martin-soaring-dev](https://github.com/Martin-soaring-dev)**: prepared the plugin for public contribution (packaging, plugin-contract checks, docs & CI) and submitted the contribution branch that became the basis for the open-source releases ([#6](https://github.com/feiyang-dev/dsh-usage-plugin/pull/6)).
303
- - **[@mumuer1024](https://github.com/mumuer1024)**: reported and diagnosed the persistence-path drift across workspaces (history "disappearing" / counted as 0) and proposed storing data in a fixed, dedicated directory ([#4](https://github.com/feiyang-dev/dsh-usage-plugin/issues/4)).
304
- - **[@liu3734](https://github.com/liu3734)**: reported and diagnosed the Windows-only path handling / spawn issues on macOS (POSIX) and proposed the cross-platform fix ([#1](https://github.com/feiyang-dev/dsh-usage-plugin/issues/1)).
305
-
306
- ## License
307
-
308
- MIT © dsh-usage-plugin
1
+ <div align="center">
2
+
3
+ # DeepSeek Harness Usage & Cost Tracker (dsh-usage-plugin)
4
+
5
+ **English** · [简体中文](./README.zh.md)
6
+
7
+ [GitHub](https://github.com/feiyang-dev/dsh-usage-plugin) · [npm](https://www.npmjs.com/package/@feiyang666/dsh-usage-plugin) · MIT License
8
+
9
+ **A community plugin for DeepSeek Harness** — records token usage and cost for every model call, with peak/off-peak billing, balance query, a calendar heatmap, and CSV / JSON / PNG export.
10
+
11
+ ![License](https://img.shields.io/badge/license-MIT-blue.svg)
12
+ ![Node](https://img.shields.io/badge/node-%3E%3D18-339933)
13
+ ![Platform](https://img.shields.io/badge/platform-web%20%26%20desktop-4d9fff)
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ > ## 🔔 Important Notice (2026-08-16): npm package renamed
20
+ >
21
+ > The **npm package has been renamed from `@feiyang666/deepseekharnessdesktop` to `@feiyang666/dsh-usage-plugin`** (matching the GitHub repo `feiyang-dev/dsh-usage-plugin`).
22
+ >
23
+ > - Use the new package name for install / upgrade: `dsh plugin --profile web add @feiyang666/dsh-usage-plugin`
24
+ > - The old package `@feiyang666/deepseekharnessdesktop` remains published for a while, but it is **no longer maintained and will not receive updates** — please migrate soon.
25
+ > - The desktop client ([`DeepSeek Harness Desktop`](https://github.com/feiyang-dev/DeepSeek-Harness-Desktop)) supports both package names and will auto-detect old-name installs with a **one-click update** to the new name.
26
+
27
+ ---
28
+
29
+ ## Overview
30
+
31
+ dsh-usage-plugin is a **usage & cost tracker** plugin in the DeepSeek Harness ecosystem (a DSH plugin shipped as a Host + Client two-in-one package). After installation, **"Usage & Cost"** and **"Balance Query"** tabs appear in the Web UI, right after "Conversation" and "Trace":
32
+
33
+ > Supports **Windows / macOS / Linux**: paths are handled per platform (`node:path`), and the folder picker / "reveal in file manager" use each OS's native mechanism (macOS: `osascript` / `open`; Linux: `zenity` / `xdg-open`). Balance query and export do not depend on Windows-only commands.
34
+
35
+ - **Usage & Cost**: records each model call's token usage and cache hits (input miss / cache hit / cache write / output / reasoning / finish reason), and computes cost using DeepSeek's peak/valley or base pricing (peak hours on weekdays are automatically priced by Beijing time 09:00–12:00 and 14:00–18:00; since 2026-08-23 weekends are billed entirely at the off-peak rate). Model names come from the actual request parameters, so non-DeepSeek models are shown truthfully instead of "unknown model"; models without an official price are counted as 0. The overview shows a by-model table plus a by-API-provider × model drill-down (each provider grouped with every model's calls and peak/off-peak cost split) and a grand total row. The overview also supports **date filtering** (Today / Last 7 days / Last 30 days / All, plus a custom start–end range), so the aggregate stats can be scoped to any single day or date range.
36
+ - **Usage Calendar**: a monthly daily-usage heatmap (colored by cost or call count), hover for details including the peak/off-peak cost split, click a day for its call list and peak/off-peak totals, plus a per-day statistics table with peak cost / off-peak cost / total columns and monthly rollups.
37
+ - **Cache Hit List**: newest-first, fully scrollable, with quick filters (Today / 7 days / 30 days / All) and custom date ranges; the summary line and footer total split peak vs off-peak consumption with a grand cost total. The list is paginated (100 rows per page), so it stays smooth even with large data volumes.
38
+ - **Price Table**: the official DeepSeek API price table (covering `deepseek-v4-flash` / `deepseek-v4-flash-vision-exp` / `deepseek-v4-pro`) — base and peak/valley unit prices shown side by side (peak vs off-peak), editable in-panel and persisted to `pricing.json`, with a reset-to-default option.
39
+ - **Balance Query**: queries your DeepSeek account balance using the configured `DEEPSEEK_API_KEY`.
40
+ - **Export**: CSV / JSON / **PNG long image** (newest-first, up to the latest 2000 records, warns if exceeded; the PNG report includes peak/off-peak cost columns), to any directory (native picker), auto-opens the folder after export.
41
+ - **Import**: merge-imports JSON / CSV files, deduplicated by time.
42
+ - **Persistence**: records are written live to `<session workspace>/dsh-usage/usage-records.json` and restored on restart (cap 100000 records).
43
+ - **UI adaptation**: panel typography scales with the app's display-size setting (em-relative fonts); table wrapping and spacing are tuned so large display sizes stay readable.
44
+ - **English UI (i18n)**: the panel auto-detects your browser language — Chinese browsers keep 中文, everyone else gets English; a toggle button next to Refresh switches instantly, and the choice persists via `localStorage` (`dsh-usage-lang`). Panel content switches immediately; the host-level Conversation/Settings tab labels are registered once at boot and pick up the new language after a page reload.
45
+
46
+ ---
47
+
48
+ ## Screenshots
49
+
50
+ ### Usage & Consumption
51
+ ![Usage & Consumption](./docs/assets/usage-overview.png)
52
+
53
+ ### Balance Query
54
+ ![Balance Query](./docs/assets/balance-query.png)
55
+
56
+ ## Recommended Installation
57
+
58
+ > Either method works and is equivalent. **We recommend the desktop app** — fully graphical, no command line needed.
59
+
60
+ ### Option 1 (recommended): One-click via the desktop app
61
+
62
+ Install [DeepSeek Harness Desktop](https://github.com/feiyang-dev/DeepSeek-Harness-Desktop), open it, then go to **"Install Plugins" → Recommended → Usage & Cost Tracker → Install** and click **"Restart Service Now"** to activate.
63
+
64
+ ### Option 2: Command line
65
+
66
+ ```bash
67
+ # Prerequisite: install dsh (npm install -g @deepseek-ai/dsh)
68
+ dsh plugin --profile web add @feiyang666/dsh-usage-plugin
69
+ ```
70
+
71
+ Or install to another profile:
72
+
73
+ ```bash
74
+ dsh plugin --profile web add @feiyang666/dsh-usage-plugin
75
+ dsh plugin --profile headless add @feiyang666/dsh-usage-plugin
76
+ ```
77
+
78
+ Restart the dsh web service after installation. Detailed manual install / wiring / uninstall / troubleshooting follows below.
79
+
80
+ ---
81
+
82
+ ## What's in the package
83
+
84
+ One npm package = a **host half** (Node-side Cordis plugin: recording, billing, balance query, export — see `lib/index.js`) + a **client half** (browser-side panel — see `lib/client.js`, which talks to the host via `/usage/api`).
85
+
86
+ The package integrates with DSH through two declarations:
87
+
88
+ | Declaration | Purpose |
89
+ | --- | --- |
90
+ | `dsh.bundle.patch` (`cordis.patch.yml`) | Lets DSH recognize it as a **standard bundle plugin package**: `dsh plugin --profile <name> add <package>` installs and wires it in one command, no manual config editing |
91
+ | `dsh.client` + `exports["./client"]` | Lets the web client auto-load the browser panel at `/plugins/<package>/client.js` |
92
+
93
+ So for users, **installation is one command** — no YAML editing, no manual file copying.
94
+
95
+ ---
96
+
97
+ ## Installation (for users)
98
+
99
+ ### 0. Prerequisites
100
+
101
+ - DeepSeek Harness installed (`npm install -g @deepseek-ai/dsh`, or a desktop app built on it, or `npx @deepseek-ai/dsh web`).
102
+ - Option A (recommended) needs **pnpm**: `npm install -g pnpm` (or `corepack enable`).
103
+ - Make sure `dsh` is on PATH (for the desktop app, run in its bundled terminal).
104
+
105
+ ### 1. Method A (recommended): one command
106
+
107
+ ```bash
108
+ dsh plugin --profile web add @feiyang666/dsh-usage-plugin
109
+ ```
110
+
111
+ This does three things (all automatic):
112
+
113
+ 1. Installs the package via pnpm into `~/.dsh/profiles/web` (auto-initializes the profile on first use);
114
+ 2. Detects the package's `dsh.bundle` declaration and writes the package name into the profile's `dsh.profile.bundles` layer list;
115
+ 3. After restart, DSH reads the package's `cordis.patch.yml` and mounts the plugin row into the app tree — **no manual config editing**.
116
+
117
+ Same for other profiles (replace `web` with your profile name, e.g. `dsh plugin --profile headless add ...`; `dsh web` equals `dsh --profile web`).
118
+
119
+ > Test a local tarball: `dsh plugin --profile web add C:\path\to\feiyang666-dsh-usage-plugin-1.9.0.tgz`
120
+
121
+ ### 2. Method B: manual install (no pnpm / no `dsh plugin`)
122
+
123
+ Only for when you have no pnpm or want full manual control. **Do not `npm install` directly at `~/.dsh/profiles`** (that dir has no package.json; npm would treat the whole node_modules as residue and wipe it).
124
+
125
+ **B1. Use pnpm but not `dsh plugin`:**
126
+
127
+ ```bash
128
+ cd ~/.dsh/profiles/web
129
+ pnpm add @feiyang666/dsh-usage-plugin
130
+ # then manually append the plugin row to web/cordis.patch.yml (see B3) and restart
131
+ ```
132
+
133
+ **B2. Or use npm:** add a minimal package.json to the profile first, then install:
134
+
135
+ ```bash
136
+ cd ~/.dsh/profiles/web
137
+ # if no package.json exists there yet (only after `dsh plugin` init):
138
+ # echo '{"name":"dsh-profile-web","private":true,"dependencies":{}}' > package.json
139
+ npm install @feiyang666/dsh-usage-plugin
140
+ ```
141
+
142
+ **B3. Wire it up (once, idempotent):** append to `~/.dsh/profiles/web/cordis.patch.yml`:
143
+
144
+ ```yaml
145
+ - insert:
146
+ - id: usage-plugin
147
+ name: '@feiyang666/dsh-usage-plugin'
148
+ inject:
149
+ - fs
150
+ - webServer
151
+ - subprocess
152
+ - credentials
153
+ - sandboxPolicy
154
+ - agents
155
+ ```
156
+
157
+ Or just run the package's built-in wiring script (auto-finds the profile and appends, idempotent):
158
+
159
+ ```bash
160
+ node node_modules/@feiyang666/dsh-usage-plugin/scripts/wire.js
161
+ ```
162
+
163
+ > ⚠️ The `inject` list is **required**: it makes Cordis wait until `fs` / `webServer` / `subprocess` / `credentials` / `sandboxPolicy` / `agents` are ready before activating the plugin. Without it the `/usage/api` route never registers and the panel fails with `Unexpected end of JSON input`.
164
+
165
+ ### 3. Method C: desktop app
166
+
167
+ The desktop app (e.g. [DeepSeek Harness Desktop](https://github.com/feiyang-dev/DeepSeek-Harness-Desktop)) uses the same `~/.dsh/profiles` underneath. Run Method A's command in any terminal, restart the app, and the plugin activates automatically (the app starts the same `dsh web`).
168
+
169
+ ### 4. Restart and verify
170
+
171
+ Restart the DeepSeek Harness web app (command line: kill the old process and re-run `dsh web`; desktop: fully quit and reopen). Then:
172
+
173
+ - Refresh http://127.0.0.1:3080 — after "Conversation" and "Trace", you should see **"Usage & Cost"** and **"Balance Query"** tabs; there are entries in Settings too.
174
+ - The "Usage & Cost" panel contains **Overview / Usage Calendar / Cache Hit List / Price Table** subtabs.
175
+ - Send a message and the "Usage & Cost" panel should show this call's token / cost record.
176
+
177
+ ### 5. Configuration (for balance query)
178
+
179
+ "Balance Query" uses the configured `DEEPSEEK_API_KEY`: set the API Key in **Settings → Models** (same key used for chats), then open the "Balance Query" tab and click "Query Balance".
180
+
181
+ ---
182
+
183
+ ## Uninstall
184
+
185
+ ```bash
186
+ dsh plugin --profile web remove @feiyang666/dsh-usage-plugin
187
+ ```
188
+
189
+ (Equivalent to pnpm remove; `dsh plugin` auto-removes the package name from the `dsh.profile.bundles` layer list.) Restart the app afterward.
190
+
191
+ For manual installs (Method B), do it in reverse: remove the `usage-plugin` row from `cordis.patch.yml`, then `pnpm remove` / `npm uninstall` the package, and restart.
192
+
193
+ > Upgrading from a 1.0.x manual-wiring install to 1.1.x: first remove the old `usage-plugin` row from `cordis.patch.yml` (or follow the uninstall flow), then reinstall via Method A to avoid mounting the plugin twice.
194
+
195
+ ---
196
+
197
+ ## How to update
198
+
199
+ Releasing happens on npm, so updating just means pulling the latest published package. Your usage history is **safe** — since v1.9.2 it lives in a fixed dedicated directory (not in any profile / workspace), so an update never wipes it.
200
+
201
+ ### Desktop app
202
+ Open **"Install Plugins"** → find **Usage & Cost Tracker** → click **Update** (or **Re-install**) → **"Restart Service Now"**. If there is no Update button, just remove then re-add it.
203
+
204
+ ### Command line (Method A)
205
+ Re-running `add` is idempotent and pulls the newest version:
206
+
207
+ ```bash
208
+ dsh plugin --profile web add @feiyang666/dsh-usage-plugin
209
+ dsh web # restart
210
+ ```
211
+
212
+ Pin a specific version:
213
+
214
+ ```bash
215
+ dsh plugin --profile web add @feiyang666/dsh-usage-plugin@1.9.3
216
+ ```
217
+
218
+ ### Manual install (Method B)
219
+ In the profile dir:
220
+
221
+ ```bash
222
+ cd ~/.dsh/profiles/web
223
+ pnpm update @feiyang666/dsh-usage-plugin # or: npm update @feiyang666/dsh-usage-plugin
224
+ ```
225
+
226
+ ### Verify the installed version
227
+ ```bash
228
+ npm ls @feiyang666/dsh-usage-plugin --prefix ~/.dsh/profiles/web
229
+ ```
230
+
231
+ > ⚠️ **Do not hand-edit files under `~/.dsh/profiles/web/node_modules/@feiyang666/dsh-usage-plugin/`** (e.g. `lib/index.js` / `lib/client.js`). Every update re-extracts the package from npm and overwrites those files, so local edits are silently lost. To change behavior, fork the repo and publish your own version, or contribute upstream.
232
+
233
+ ---
234
+
235
+ ## Data & locations
236
+
237
+ > **Since v1.9.2**, records are stored in a **fixed, dedicated data directory** (fixes [#4](https://github.com/feiyang-dev/dsh-usage-plugin/issues/4)). The path no longer follows the session workspace / `~/.dsh` / desktop-app install dir, so your history never "disappears" (counted as 0) when the workspace changes, and the path shown in the UI equals the on-disk path.
238
+
239
+ - **Records**: `<data root>/dsh-usage/usage-records.json`
240
+ - Resolution order for the **data root** (data always lands in the **first writable** dir of this list, **never in the workspace** unless all of the below are unwritable):
241
+ 1. env var `DSH_USAGE_DATA_DIR` (if set) overrides everything;
242
+ 2. Windows: `%LOCALAPPDATA%\dsh-usage-plugin` (falls back to `%APPDATA%` if `LOCALAPPDATA` is unset);
243
+ 3. user home dir: `~/dsh-usage-data` (Windows `%USERPROFILE%\dsh-usage-data`, macOS/Linux `~/dsh-usage-data`);
244
+ 4. **fallback (rare)**: current workspace `<workspace>/dsh-usage` only used when all system/user dirs above are unwritable, and the panel will show a "persistence disabled" warning.
245
+ - **Writes bypass the model sandbox**: persistence is done by the host plugin process's own filesystem, not subject to the `workspace-write` sandbox, so the fixed directory is always writable and data is not lost when switching workspaces.
246
+ - Default on Windows: `%LOCALAPPDATA%\dsh-usage-plugin\dsh-usage\usage-records.json`
247
+ - **Legacy data auto-merge**: on first start, records previously scattered in `%USERPROFILE%\dsh-usage`, `~/.dsh/dsh-usage`, and each workspace's `dsh-usage` (or `.dsh-usage-records.json`) are merged into the fixed root, deduplicated by `time` — no manual migration needed.
248
+ - Price config (edited & saved in the panel): `<data root>/dsh-usage/pricing.json`
249
+ - Default export dir: `<data root>/dsh-usage/{csv,json,images}/`
250
+ - Custom export dir: set in the panel's "Export target directory" or click "Choose directory…"
251
+ - Startup diagnostics (if the plugin fails to activate): `dsh-usage-boot.log` next to the data root
252
+
253
+ ---
254
+
255
+ ## FAQ
256
+
257
+ | Symptom | Cause / Fix |
258
+ | --- | --- |
259
+ | Panel reports `Unexpected end of JSON input` | The plugin row is missing the `inject` list, so the route isn't registered. Add the inject list per Method B3 and restart |
260
+ | Panel blank / no top tab | Plugin not activated. Check `dsh-usage-boot.log`; confirm the `cordis.patch.yml` row exists with the correct `name` |
261
+ | Balance query fails with "DEEPSEEK_API_KEY not configured" | Set the API Key in Settings Models |
262
+ | Balance query network error | Ensure `api.deepseek.com` is reachable (configure a proxy if needed) |
263
+ | `dsh plugin` reports pnpm not found | Install pnpm: `npm install -g pnpm` |
264
+ | Install can't reach the npm registry | Set a mirror: `npm config set registry https://registry.npmmirror.com` (or `pnpm config set registry ...`) and retry |
265
+ | After uninstall, still reports `Cannot find package '@feiyang666/...'` | A package reference remains in the profile. Remove the corresponding row from `cordis.patch.yml` and the package name from `dsh.profile.bundles`, then restart |
266
+
267
+ ---
268
+
269
+ ## Related Projects
270
+
271
+ | Project | Description | Installation |
272
+ | --- | --- | --- |
273
+ | [DeepSeek Harness Desktop](https://github.com/feiyang-dev/DeepSeek-Harness-Desktop) | Windows desktop console: install/start/stop/restart the dsh web service with one click, built-in plugin management **install this plugin from its Recommended section** | Download the desktop app and click a few buttons |
274
+ | [Data Vault (dsh-vault)](https://github.com/feiyang-dev/dsh-vault) | Auto backup / wipe detection / one-click restore — protects chat history and workspace data | One-click from the desktop app, or `dsh plugin add @feiyang666/dsh-vault` |
275
+ | [DeepSeek-Harness](https://github.com/deepseek-ai/DeepSeek-Harness) | Official CLI / Web service | Quick start below |
276
+
277
+ ### Running DeepSeek Harness
278
+
279
+ **Quick start (via npm)**
280
+
281
+ Install Node.js, then run:
282
+
283
+ ```bash
284
+ npx @deepseek-ai/dsh web
285
+ ```
286
+
287
+ This command starts the Web UI at the default address http://127.0.0.1:3080. See the [Web UI Guide](https://github.com/deepseek-ai/DeepSeek-Harness) for details.
288
+
289
+ **Run from source**
290
+
291
+ To run from the repository source:
292
+
293
+ ```bash
294
+ git clone https://github.com/deepseek-ai/deepseek-harness.git
295
+ cd deepseek-harness
296
+ pnpm install
297
+ pnpm run build
298
+ pnpm dsh web
299
+ ```
300
+
301
+ ## Acknowledgements
302
+
303
+ - **[@ayleen](https://github.com/ayleen)**: implemented the full English UI layer (i18n) with reactive language switching, and moved balance presentation to semantic keys ([#7](https://github.com/feiyang-dev/dsh-usage-plugin/pull/7)).
304
+ - **[@wuhuqif176](https://github.com/wuhuqif176)**: added the Bailian (Qwen) Token Plan quota query to the balance panel ([#8](https://github.com/feiyang-dev/dsh-usage-plugin/pull/8)).
305
+ - **[@Martin-soaring-dev](https://github.com/Martin-soaring-dev)**: prepared the plugin for public contribution (packaging, plugin-contract checks, docs & CI) and submitted the contribution branch that became the basis for the open-source releases ([#6](https://github.com/feiyang-dev/dsh-usage-plugin/pull/6)).
306
+ - **[@mumuer1024](https://github.com/mumuer1024)**: reported and diagnosed the persistence-path drift across workspaces (history "disappearing" / counted as 0) and proposed storing data in a fixed, dedicated directory ([#4](https://github.com/feiyang-dev/dsh-usage-plugin/issues/4)).
307
+ - **[@liu3734](https://github.com/liu3734)**: reported and diagnosed the Windows-only path handling / spawn issues on macOS (POSIX) and proposed the cross-platform fix ([#1](https://github.com/feiyang-dev/dsh-usage-plugin/issues/1)).
308
+
309
+ ## License
310
+
311
+ MIT © dsh-usage-plugin