@rayadesu/dsh-billing 0.1.0-rc.8
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/AGENTS.md +54 -0
- package/LICENSE +21 -0
- package/README.i18n.yaml +6 -0
- package/README.md +118 -0
- package/README.zh.md +114 -0
- package/cordis.patch.yml +20 -0
- package/package.json +33 -0
- package/packages/llm-billing/README.i18n.yaml +6 -0
- package/packages/llm-billing/README.md +44 -0
- package/packages/llm-billing/README.zh.md +44 -0
- package/packages/llm-billing/lib/index.js +562 -0
- package/packages/llm-billing/lib/invariant.js +23 -0
- package/packages/llm-billing/lib/tsconfig.tsbuildinfo +1 -0
- package/packages/llm-billing/lib/typert.host.d.ts +3 -0
- package/packages/llm-billing/lib/typert.host.js +114 -0
- package/packages/llm-billing/lib/typert.remote-client.d.ts +27 -0
- package/packages/llm-billing/lib/typert.remote-client.d.ts.map +1 -0
- package/packages/llm-billing/lib/typert.remote-client.js +108 -0
- package/packages/llm-billing/lib/types/balance.d.ts +71 -0
- package/packages/llm-billing/lib/types/balance.d.ts.map +1 -0
- package/packages/llm-billing/lib/types/balance.js +187 -0
- package/packages/llm-billing/lib/types/balance.js.map +1 -0
- package/packages/llm-billing/lib/types/billing.d.ts +106 -0
- package/packages/llm-billing/lib/types/billing.d.ts.map +1 -0
- package/packages/llm-billing/lib/types/billing.js +163 -0
- package/packages/llm-billing/lib/types/billing.js.map +1 -0
- package/packages/llm-billing/lib/types/index.d.ts +49 -0
- package/packages/llm-billing/lib/types/index.d.ts.map +1 -0
- package/packages/llm-billing/lib/types/index.js +155 -0
- package/packages/llm-billing/lib/types/index.js.map +1 -0
- package/packages/llm-billing/lib/types/invariant.d.ts +16 -0
- package/packages/llm-billing/lib/types/invariant.d.ts.map +1 -0
- package/packages/llm-billing/lib/types/invariant.js +22 -0
- package/packages/llm-billing/lib/types/invariant.js.map +1 -0
- package/packages/llm-billing/lib/types/types/balance.d.ts +71 -0
- package/packages/llm-billing/lib/types/types/balance.d.ts.map +1 -0
- package/packages/llm-billing/lib/types/types/balance.js +187 -0
- package/packages/llm-billing/lib/types/types/balance.js.map +1 -0
- package/packages/llm-billing/lib/types/types/billing.d.ts +106 -0
- package/packages/llm-billing/lib/types/types/billing.d.ts.map +1 -0
- package/packages/llm-billing/lib/types/types/billing.js +170 -0
- package/packages/llm-billing/lib/types/types/billing.js.map +1 -0
- package/packages/llm-billing/lib/types/types/index.d.ts +49 -0
- package/packages/llm-billing/lib/types/types/index.d.ts.map +1 -0
- package/packages/llm-billing/lib/types/types/index.js +156 -0
- package/packages/llm-billing/lib/types/types/index.js.map +1 -0
- package/packages/llm-billing/lib/types/types/invariant.d.ts +16 -0
- package/packages/llm-billing/lib/types/types/invariant.d.ts.map +1 -0
- package/packages/llm-billing/lib/types/types/invariant.js +22 -0
- package/packages/llm-billing/lib/types/types/invariant.js.map +1 -0
- package/packages/llm-billing/lib/types/types/types.d.ts +63 -0
- package/packages/llm-billing/lib/types/types/types.d.ts.map +1 -0
- package/packages/llm-billing/lib/types/types/types.js +7 -0
- package/packages/llm-billing/lib/types/types/types.js.map +1 -0
- package/packages/llm-billing/lib/types/types.d.ts +63 -0
- package/packages/llm-billing/lib/types/types.d.ts.map +1 -0
- package/packages/llm-billing/lib/types/types.js +7 -0
- package/packages/llm-billing/lib/types/types.js.map +1 -0
- package/packages/llm-billing/node_modules/.bin/cordis +43 -0
- package/packages/llm-billing/node_modules/.bin/cordis.CMD +12 -0
- package/packages/llm-billing/node_modules/.bin/cordis.ps1 +41 -0
- package/packages/llm-billing/package.json +75 -0
- package/packages/llm-billing/src/balance.ts +164 -0
- package/packages/llm-billing/src/billing.ts +251 -0
- package/packages/llm-billing/src/index.ts +219 -0
- package/packages/llm-billing/src/invariant.ts +30 -0
- package/packages/llm-billing/src/types.ts +67 -0
- package/packages/llm-billing/tests/balance.spec.ts +254 -0
- package/packages/llm-billing/tests/billing.spec.ts +216 -0
- package/packages/llm-billing/tsconfig.json +42 -0
- package/packages/ui-billing/README.i18n.yaml +6 -0
- package/packages/ui-billing/README.md +30 -0
- package/packages/ui-billing/README.zh.md +30 -0
- package/packages/ui-billing/lib/client.js +4466 -0
- package/packages/ui-billing/lib/client.js.map +1 -0
- package/packages/ui-billing/lib/index.js +11 -0
- package/packages/ui-billing/lib/invariant.js +25 -0
- package/packages/ui-billing/lib/tsconfig.tsbuildinfo +1 -0
- package/packages/ui-billing/lib/types/client/BalanceBadge.d.ts +33 -0
- package/packages/ui-billing/lib/types/client/BalanceBadge.d.ts.map +1 -0
- package/packages/ui-billing/lib/types/client/BalanceBadge.js +166 -0
- package/packages/ui-billing/lib/types/client/BalanceBadge.js.map +1 -0
- package/packages/ui-billing/lib/types/client/index.d.ts +20 -0
- package/packages/ui-billing/lib/types/client/index.d.ts.map +1 -0
- package/packages/ui-billing/lib/types/client/index.js +55 -0
- package/packages/ui-billing/lib/types/client/index.js.map +1 -0
- package/packages/ui-billing/lib/types/client/locales.d.ts +26 -0
- package/packages/ui-billing/lib/types/client/locales.d.ts.map +1 -0
- package/packages/ui-billing/lib/types/client/locales.js +40 -0
- package/packages/ui-billing/lib/types/client/locales.js.map +1 -0
- package/packages/ui-billing/lib/types/index.d.ts +9 -0
- package/packages/ui-billing/lib/types/index.d.ts.map +1 -0
- package/packages/ui-billing/lib/types/index.js +9 -0
- package/packages/ui-billing/lib/types/index.js.map +1 -0
- package/packages/ui-billing/lib/types/invariant.d.ts +16 -0
- package/packages/ui-billing/lib/types/invariant.d.ts.map +1 -0
- package/packages/ui-billing/lib/types/invariant.js +24 -0
- package/packages/ui-billing/lib/types/invariant.js.map +1 -0
- package/packages/ui-billing/node_modules/.bin/cordis +43 -0
- package/packages/ui-billing/node_modules/.bin/cordis.CMD +12 -0
- package/packages/ui-billing/node_modules/.bin/cordis.ps1 +41 -0
- package/packages/ui-billing/node_modules/.bin/vite +43 -0
- package/packages/ui-billing/node_modules/.bin/vite.CMD +12 -0
- package/packages/ui-billing/node_modules/.bin/vite.ps1 +41 -0
- package/packages/ui-billing/package.json +76 -0
- package/packages/ui-billing/src/client/BalanceBadge.module.css +184 -0
- package/packages/ui-billing/src/client/BalanceBadge.tsx +266 -0
- package/packages/ui-billing/src/client/index.ts +80 -0
- package/packages/ui-billing/src/client/locales.ts +45 -0
- package/packages/ui-billing/src/css-modules.d.ts +6 -0
- package/packages/ui-billing/src/index.ts +9 -0
- package/packages/ui-billing/src/invariant.ts +32 -0
- package/packages/ui-billing/tests/balance-badge.client.spec.tsx +267 -0
- package/packages/ui-billing/tests/browser-plugin.client.spec.ts +205 -0
- package/packages/ui-billing/tsconfig.json +36 -0
- package/packages/ui-billing/tsdown.config.ts +3 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
DeepSeek-Harness-chat-billing 是 DeepSeek Harness 的计费插件仓库:在 Web 会话头部显示
|
|
4
|
+
DeepSeek 账户余额、本轮对话花费与今日共花费。本仓库是插件的**唯一分发来源**——
|
|
5
|
+
deepseek-harness 官方仓库([deepseek-ai/deepseek-harness](https://github.com/deepseek-ai/deepseek-harness))
|
|
6
|
+
不含计费插件;插件曾短暂集成于本用户的 fork,现已回退到官方提交版本(`141eb6fef8`),
|
|
7
|
+
本仓库不再依赖任何 fork。
|
|
8
|
+
|
|
9
|
+
## 仓库布局
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
packages/llm-billing/ 宿主插件 @rayadesu/dsh-llm-billing(/user/balance 传输、峰谷计价、billing Remote)
|
|
13
|
+
packages/ui-billing/ 浏览器插件 @rayadesu/dsh-client-ui-billing(会话头部徽标与详情面板)
|
|
14
|
+
cordis.patch.yml DSH profile bundle 补丁层:挂载 llm-billing + ui-billing 两个插件行
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## DSH 集成方式
|
|
18
|
+
|
|
19
|
+
- **bundle(推荐)**:根 `package.json` 声明 `dsh.bundle.patch`,`cordis.patch.yml`
|
|
20
|
+
挂载两个插件行。三个包已发布到 npm(`@rayadesu` scope),pnpm 不会把 bundle 的
|
|
21
|
+
本地依赖装进 profile,所以一条命令同时安装 bundle 与两个包(让行名能从 profile 的
|
|
22
|
+
node_modules 解析):
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
dsh plugin --profile web add @rayadesu/dsh-billing @rayadesu/dsh-llm-billing @rayadesu/dsh-client-ui-billing
|
|
26
|
+
```
|
|
27
|
+
- **手动**:把 `cordis.patch.yml` 的 insert 合并进 `$DSH_HOME/profiles/<name>/cordis.patch.yml`,
|
|
28
|
+
并用 `dsh plugin --profile <name> add @rayadesu/dsh-llm-billing @rayadesu/dsh-client-ui-billing`
|
|
29
|
+
安装两个包(行名解析同上)。
|
|
30
|
+
|
|
31
|
+
## 约定
|
|
32
|
+
|
|
33
|
+
- **源文件以本仓库为准**:`packages/*/src` 与 `tests/` 没有上游 fork,改动直接在本仓库进行。
|
|
34
|
+
- **不在本仓库构建**:tsconfig 依赖 deepseek-harness monorepo 布局
|
|
35
|
+
(`tsconfig.base*.json`、vendor/ 引用),构建需在任意 deepseek-harness checkout 环境中
|
|
36
|
+
进行(把两个包放入 `packages/llm/llm-billing` 与 `packages/client/ui-billing` 位置后
|
|
37
|
+
构建),再把生成的 `lib/` 同步回本仓库对应包目录;`lib/` 已 gitignore,不进仓库。
|
|
38
|
+
- **依赖以发布形态声明**:`@deepseek-ai/dsh-*` 依赖写 `^0.1.0-rc.8`(npm `next` tag 上的
|
|
39
|
+
发布形态,对应官方 monorepo 里的 `workspace:^`);本插件的三个包发布到 npm 的
|
|
40
|
+
`@rayadesu` scope,直接 `dsh plugin add @rayadesu/...` 安装。
|
|
41
|
+
- **密钥不进仓库**:`DEEPSEEK_API_KEY` 等一律由用户环境或凭据 seam 提供,仓库不含真实值。
|
|
42
|
+
- **README 双语**:每个 README 遵循 DSH 结构 `README.md`(EN) + `README.zh.md`(ZH) +
|
|
43
|
+
`README.i18n.yaml`(记录两文件 git blob hash,改动后需更新)。
|
|
44
|
+
- **版本对齐**:根 bundle 与两个包统一版本号(当前 0.1.0-rc.8),`pnpm-lock.yaml` 随依赖变更更新。
|
|
45
|
+
- **文本规范**:LF 换行、文件末尾一个换行(`.editorconfig`/`.gitattributes` 已声明)。
|
|
46
|
+
|
|
47
|
+
## 常用命令
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
pnpm install # 安装本仓库依赖(dsh-* 从 registry 解析)
|
|
51
|
+
dsh plugin --profile web add @rayadesu/dsh-billing @rayadesu/dsh-llm-billing @rayadesu/dsh-client-ui-billing # 安装进 DSH
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
改动后至少校验 JSON/YAML 可解析,并更新受影响包的 README(双语都要)。
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 WilliamLIiii
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Bilingual-pair consistency record: the git blob hash of each side as of the
|
|
2
|
+
# last confirmed-consistent state. Both languages carry equal authority; after
|
|
3
|
+
# editing either side, bring the other along and re-record both hashes with:
|
|
4
|
+
# git hash-object README.md README.zh.md
|
|
5
|
+
README.md: a9771710292f8567ecbf3eb0cca14157ffe28bba
|
|
6
|
+
README.zh.md: f8b2f62ea4c4ad46d4e05e2625ae1e9c70806e1c
|
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# DeepSeek Harness billing plugin
|
|
2
|
+
|
|
3
|
+
English | [中文](README.zh.md)
|
|
4
|
+
|
|
5
|
+
A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) plugin that shows your **DeepSeek account balance**, **this session's (this conversation's) billed spend**, and **today's total spend across all sessions** directly in the web session header.
|
|
6
|
+
|
|
7
|
+
> The balance is the real `GET /user/balance` figure; the session and today spends price each message's billed tokens at the official peak/off-peak rates and are estimates, not billing promises.
|
|
8
|
+
|
|
9
|
+
## What it shows
|
|
10
|
+
|
|
11
|
+
- **Session-header badge** — two lines: remaining balance (`剩余额度:¥X`) and this conversation's billed spend (`本轮对话花费:¥X`).
|
|
12
|
+
- **Detail panel** — the remaining amount, this session's spend (`本会话花费`) with today's all-session spend beside it (`今日共花费`), one priced row per model (`缓存命中 ¥X · 未命中输入 ¥Y · 输出 ¥Z`), plus a manual refresh action and a spend disclaimer.
|
|
13
|
+
- **Failures and empty states** — a session or day without priced usage shows "no usage recorded" instead of a fabricated figure; a missing key, rejected credential, or transport error renders a muted "Balance unavailable" whose tooltip carries the Remote's own error message.
|
|
14
|
+
|
|
15
|
+
## Data update mechanics
|
|
16
|
+
|
|
17
|
+
- **Session spend follows the conversation** — on every new message in the current session, the badge recomputes only **this session's spend** and **today's spend** (purely local pricing, no network request), so the spend lines stay live during an ongoing conversation.
|
|
18
|
+
- **Balance stays manual** — the balance is account-level data, queried only on mount, session switch, the manual refresh action, or a browser reload; **there is no polling** and it does not track account changes by itself.
|
|
19
|
+
- **Old values survive refreshes** — a failed refresh keeps the last good value instead of blanking it.
|
|
20
|
+
|
|
21
|
+
## Preview
|
|
22
|
+
<img width="505" height="264" alt="image" src="billing-preview.png" />
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## Package layout
|
|
26
|
+
|
|
27
|
+
| Package | Side | Role |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| [`packages/llm-billing`](packages/llm-billing) — `@rayadesu/dsh-llm-billing` | Host | Owns the `/user/balance` transport and the peak/off-peak pricing table. Exposes the `billing` Remote (`getBalance`, `getSessionSpend`, `getTodaySpend`). |
|
|
30
|
+
| [`packages/ui-billing`](packages/ui-billing) — `@rayadesu/dsh-client-ui-billing` | Browser | Mounts the `billing` Remote itself and contributes the session-header badge and detail panel. |
|
|
31
|
+
|
|
32
|
+
## Prerequisites
|
|
33
|
+
|
|
34
|
+
- **DeepSeek Harness** (`dsh`) — the plugin runs inside a dsh profile.
|
|
35
|
+
- **A DeepSeek API key** — the balance is read from the DeepSeek API, so every user needs their own key.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
> 📌 **About this repository**: this repo is the plugin's **only distribution
|
|
40
|
+
> source** — the official [deepseek-harness](https://github.com/deepseek-ai/deepseek-harness)
|
|
41
|
+
> repository does **not** ship the billing plugin. It was briefly integrated into
|
|
42
|
+
> this user's fork, which has since been reverted to the official commit
|
|
43
|
+
> (`141eb6fef8`); this repo no longer depends on any fork.
|
|
44
|
+
|
|
45
|
+
### Installation (published to npm, one command)
|
|
46
|
+
|
|
47
|
+
The three packages are published to npm under the `@rayadesu` scope. Install
|
|
48
|
+
the bundle plus the two plugin packages in one command (pnpm does not install
|
|
49
|
+
the bundle's local dependencies into the profile, so the two plugin packages
|
|
50
|
+
must be named explicitly):
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
dsh plugin --profile web add @rayadesu/dsh-billing @rayadesu/dsh-llm-billing @rayadesu/dsh-client-ui-billing
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Manual rows (only when you do not want the bundle):
|
|
57
|
+
|
|
58
|
+
```yaml
|
|
59
|
+
# ~/.dsh/profiles/web/cordis.patch.yml
|
|
60
|
+
- insert:
|
|
61
|
+
- id: llm-billing
|
|
62
|
+
name: '@rayadesu/dsh-llm-billing'
|
|
63
|
+
- id: ui-billing
|
|
64
|
+
name: '@rayadesu/dsh-client-ui-billing'
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Dependency notes
|
|
68
|
+
|
|
69
|
+
The runtime dependencies (`@deepseek-ai/dsh-credentials` and friends) are published
|
|
70
|
+
to npm (`0.1.0-rc.8` on the `next` tag); both manifests declare them as
|
|
71
|
+
`^0.1.0-rc.8` (the published form of the official `workspace:^`), so `pnpm install`
|
|
72
|
+
resolves them directly.
|
|
73
|
+
|
|
74
|
+
### Configure your DeepSeek API key
|
|
75
|
+
|
|
76
|
+
Either fill it in on the web "Models" page (writes `DEEPSEEK_API_KEY` into `~/.dsh/.credentials.yaml`), or export it:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
export DEEPSEEK_API_KEY=sk-...
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Restart
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
dsh web
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Configuration
|
|
89
|
+
|
|
90
|
+
Both packages ship sane defaults; everything below is optional.
|
|
91
|
+
|
|
92
|
+
### Host (`llm-billing`)
|
|
93
|
+
|
|
94
|
+
| Field | Default | Meaning |
|
|
95
|
+
| --- | --- | --- |
|
|
96
|
+
| `apiKeyEnv` | `DEEPSEEK_API_KEY` | Credential-reference (environment-variable) name resolved per call. |
|
|
97
|
+
| `baseURL` | `$DEEPSEEK_BASE_URL` then `https://api.deepseek.com` | Endpoint base; `/user/balance` is appended. |
|
|
98
|
+
| `models` | V4 Flash + V4 Pro + V4 Flash Vision Exp | Advisory display rows, in presentation order. |
|
|
99
|
+
| `billing.peakHours` | 09:00–12:00, 14:00–18:00 (Beijing) | Peak-hour windows; all other hours are off-peak. |
|
|
100
|
+
| `billing.models` | Published V4 rates | Per-model peak/off-peak price rows (`cacheHitInput`, `cacheMissInput`, `output`, in CNY per 1M tokens). |
|
|
101
|
+
|
|
102
|
+
## How session spend is computed
|
|
103
|
+
|
|
104
|
+
- Each `assistant/message` event reports three billed token buckets: **cache-hit input**, **cache-miss input** (uncached input + cache writes), and **output** (including reasoning).
|
|
105
|
+
- Each message is priced at the peak/off-peak rate of its own **Beijing-time** hour, the three buckets are billed separately (`缓存命中 ¥X · 未命中输入 ¥Y · 输出 ¥Z`), then summed per model.
|
|
106
|
+
- **Today's spend** aggregates every session's events on the current Beijing-time calendar day with the same pricing rules; event dates are also assigned in Beijing time.
|
|
107
|
+
- Models without a rate row are not priced (the built-in catalog currently has the three V4 rows: V4 Flash, V4 Pro, and V4 Flash Vision Exp). Rates follow the DeepSeek pricing effective **August 17** (Beijing-time peak/off-peak hours).
|
|
108
|
+
|
|
109
|
+
## Known limitations
|
|
110
|
+
|
|
111
|
+
- **Priced rows only** — the session and today spends only price models that have a `billing.models` row.
|
|
112
|
+
- **On-demand read** — today's spend reads every session's full event log on each refresh, so cost grows with total log size.
|
|
113
|
+
- **Balance does not follow automatically** — the balance stays a manual snapshot (no polling); spending from another client does not move the shown value until a refresh or browser reload.
|
|
114
|
+
- **Estimate, not a promise** — the session spend prices tokens at official rates; the provider's actual billing prevails.
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
[MIT](LICENSE)
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# DeepSeek Harness 计费插件
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 中文
|
|
4
|
+
|
|
5
|
+
一个 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 插件,在 Web 会话头部直接显示你的 **DeepSeek 账户余额**、**当前会话(本轮对话)的花费**,以及**今日所有会话的共花费**。
|
|
6
|
+
|
|
7
|
+
> 余额是 `GET /user/balance` 的真实数字;会话花费与今日共花费是按官方峰/谷单价对每条消息的计费 token 逐条计价的结果,不是计费承诺。
|
|
8
|
+
|
|
9
|
+
## 显示什么
|
|
10
|
+
|
|
11
|
+
- **会话头部徽标** —— 两行:剩余余额(`剩余额度:¥X`)+ 本轮对话的计费花费(`本轮对话花费:¥X`)。
|
|
12
|
+
- **详情面板** —— 剩余金额、本会话花费(`本会话花费`)与其右侧的今日所有会话共花费(`今日共花费`),以及每个模型一行的花费分项(`缓存命中 ¥X · 未命中输入 ¥Y · 输出 ¥Z`),外加手动刷新按钮与花费说明。
|
|
13
|
+
- **失败与空态** —— 会话或今日没有可计价消耗时显示「暂无消耗记录」而不是编造数字;未配置 key、凭据被拒或传输错误时显示弱化的「额度不可用」,其提示携带 Remote 自己的错误信息。
|
|
14
|
+
|
|
15
|
+
## 数据更新机制
|
|
16
|
+
|
|
17
|
+
- **会话花费自动跟随** —— 当前会话每到达一条新消息,徽标就只重算**本会话的花费**与**今日共花费**(纯本地计价,不发网络请求),连续对话时花费会实时跟着走。
|
|
18
|
+
- **额度保持手动** —— 余额是账户级数据,只在挂载、切换会话、手动点刷新、或刷新浏览器时重新查询 `/user/balance`;**没有轮询**,不会自动跟随账户变化。
|
|
19
|
+
- **刷新期间旧值保留** —— 刷新失败保留上一次有效值,不会清空。
|
|
20
|
+
|
|
21
|
+
## 显示样式
|
|
22
|
+
<img width="505" height="264" alt="image" src="billing-preview.png" />
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## 包结构
|
|
26
|
+
|
|
27
|
+
| 包 | 侧 | 作用 |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| [`packages/llm-billing`](packages/llm-billing) —— `@rayadesu/dsh-llm-billing` | 主机端 | 负责 `/user/balance` 传输与峰/谷计价表。对外暴露 `billing` Remote(`getBalance`、`getSessionSpend`、`getTodaySpend`)。 |
|
|
30
|
+
| [`packages/ui-billing`](packages/ui-billing) —— `@rayadesu/dsh-client-ui-billing` | 浏览器端 | 自己挂载 `billing` Remote,并贡献会话头部徽标与详情面板。 |
|
|
31
|
+
|
|
32
|
+
## 前置条件
|
|
33
|
+
|
|
34
|
+
- **DeepSeek Harness**(`dsh`)—— 插件运行在 dsh profile 内。
|
|
35
|
+
- **一个 DeepSeek API key** —— 余额从 DeepSeek API 读取,所以每个用户都需要自己的 key。
|
|
36
|
+
|
|
37
|
+
## 安装
|
|
38
|
+
|
|
39
|
+
> 📌 **仓库说明**:本仓库是插件的**唯一分发来源**——deepseek-harness 官方仓库
|
|
40
|
+
> ([deepseek-ai/deepseek-harness](https://github.com/deepseek-ai/deepseek-harness))
|
|
41
|
+
> **不含**计费插件;插件曾短暂集成于本用户的 fork,现已回退到官方提交版本
|
|
42
|
+
> (`141eb6fef8`),本仓库不再依赖任何 fork。
|
|
43
|
+
|
|
44
|
+
### 安装(已发布到 npm,一条命令)
|
|
45
|
+
|
|
46
|
+
三个包已发布到 npm 的 `@rayadesu` scope。一条命令同时安装 bundle 与两个插件包
|
|
47
|
+
(pnpm 不会把 bundle 的本地依赖装进 profile,所以两个插件包要显式列出):
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
dsh plugin --profile web add @rayadesu/dsh-billing @rayadesu/dsh-llm-billing @rayadesu/dsh-client-ui-billing
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
手动补行(仅当不想用 bundle 时):
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
# ~/.dsh/profiles/web/cordis.patch.yml
|
|
57
|
+
- insert:
|
|
58
|
+
- id: llm-billing
|
|
59
|
+
name: '@rayadesu/dsh-llm-billing'
|
|
60
|
+
- id: ui-billing
|
|
61
|
+
name: '@rayadesu/dsh-client-ui-billing'
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 依赖说明
|
|
65
|
+
|
|
66
|
+
`@deepseek-ai/dsh-credentials` 等运行时依赖已发布到 npm(`0.1.0-rc.8`,`next` tag),
|
|
67
|
+
两个包的 manifest 以 `^0.1.0-rc.8` 声明(官方 monorepo 中 `workspace:^` 的发布形态),
|
|
68
|
+
`pnpm install` 可直接解析。
|
|
69
|
+
|
|
70
|
+
### 配置你的 DeepSeek API key
|
|
71
|
+
|
|
72
|
+
二选一:在网页「模型」页填入(会把 `DEEPSEEK_API_KEY` 写入 `~/.dsh/.credentials.yaml`),或导出环境变量:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
export DEEPSEEK_API_KEY=sk-...
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 重启
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
dsh web
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 配置
|
|
85
|
+
|
|
86
|
+
两个包都有合理默认值,下面都是可选的。
|
|
87
|
+
|
|
88
|
+
### 主机端(`llm-billing`)
|
|
89
|
+
|
|
90
|
+
| 字段 | 默认 | 含义 |
|
|
91
|
+
| --- | --- | --- |
|
|
92
|
+
| `apiKeyEnv` | `DEEPSEEK_API_KEY` | 每次调用时解析的凭据引用(环境变量)名。 |
|
|
93
|
+
| `baseURL` | `$DEEPSEEK_BASE_URL`,其次 `https://api.deepseek.com` | 端点基础地址;会追加 `/user/balance`。 |
|
|
94
|
+
| `models` | V4 Flash + V4 Pro + V4 Flash Vision Exp | 展示用的模型行,按展示顺序。 |
|
|
95
|
+
| `billing.peakHours` | 09:00–12:00、14:00–18:00(北京) | 高峰时段窗口;其余时段为低谷。 |
|
|
96
|
+
| `billing.models` | 官方 V4 费率 | 每个模型的峰/谷单价行(`cacheHitInput`、`cacheMissInput`、`output`,单位:元/百万 token)。 |
|
|
97
|
+
|
|
98
|
+
## 会话花费是怎么算的
|
|
99
|
+
|
|
100
|
+
- 每条 `assistant/message` 事件报告三个计费 token 桶:**缓存命中输入**、**未命中输入**(未缓存输入 + 缓存写入)、**输出**(含推理)。
|
|
101
|
+
- 每条消息按其**发生时刻(北京时间)**所在的峰/谷时段单价计价,三个桶分别计费(`缓存命中 ¥X · 未命中输入 ¥Y · 输出 ¥Z`),再按模型汇总。
|
|
102
|
+
- **今日共花费**按同一个计价规则汇总当天(北京时间自然日)所有会话的事件;事件归属的日期同样按北京时间计算。
|
|
103
|
+
- 没有费率行的模型不计入(内置价目表目前含三个 V4 行:V4 Flash、V4 Pro、V4 Flash Vision Exp)。计费按 DeepSeek **8 月 17 日实行**的费率(北京时间峰/谷时段)。
|
|
104
|
+
|
|
105
|
+
## 已知限制
|
|
106
|
+
|
|
107
|
+
- **有费率行才计价** —— 会话花费与今日共花费只统计价目表(`billing.models`)里有的模型。
|
|
108
|
+
- **按需读取** —— 今日共花费每次刷新都会读取所有会话的完整事件日志,成本随总日志大小增长。
|
|
109
|
+
- **额度不自动跟随** —— 余额保持手动刷新(无轮询),账户在其他客户端产生消耗时,界面值不会自动变化,需手动刷新或刷新浏览器。
|
|
110
|
+
- **是估算,不是承诺** —— 会话花费按官方单价对 token 计价;实际计费以服务商为准。
|
|
111
|
+
|
|
112
|
+
## 许可证
|
|
113
|
+
|
|
114
|
+
[MIT](LICENSE)
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# @rayadesu/dsh-billing bundle patch for DSH.
|
|
2
|
+
#
|
|
3
|
+
# Mounts the host-side billing Remote provider (llm-billing) and the
|
|
4
|
+
# session-header balance/spend badge (ui-billing). The deepseek-harness
|
|
5
|
+
# official repo does not ship these packages, so the row names must resolve
|
|
6
|
+
# from the profile's own node_modules: install the three published packages
|
|
7
|
+
# (bundle + the two plugin packages) in one command (see below).
|
|
8
|
+
#
|
|
9
|
+
# No machine-specific literals: this patch carries only plugin ids and names;
|
|
10
|
+
# no credentials or paths are needed — the plugins read the DeepSeek API key
|
|
11
|
+
# from the credential seam / environment at runtime.
|
|
12
|
+
#
|
|
13
|
+
# Install with one command (the bundle plus the two plugin packages, since
|
|
14
|
+
# pnpm does not install the bundle's local dependencies into the profile):
|
|
15
|
+
# dsh plugin --profile web add @rayadesu/dsh-billing @rayadesu/dsh-llm-billing @rayadesu/dsh-client-ui-billing
|
|
16
|
+
- insert:
|
|
17
|
+
- id: llm-billing
|
|
18
|
+
name: '@rayadesu/dsh-llm-billing'
|
|
19
|
+
- id: ui-billing
|
|
20
|
+
name: '@rayadesu/dsh-client-ui-billing'
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rayadesu/dsh-billing",
|
|
3
|
+
"version": "0.1.0-rc.8",
|
|
4
|
+
"description": "DeepSeek Harness billing plugin: account balance and this session's billed spend with a session-header badge.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": "^22.19 || >=24"
|
|
8
|
+
},
|
|
9
|
+
"dsh": {
|
|
10
|
+
"bundle": {
|
|
11
|
+
"patch": "./cordis.patch.yml"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"cordis.patch.yml",
|
|
16
|
+
"packages/llm-billing",
|
|
17
|
+
"packages/ui-billing",
|
|
18
|
+
"README.md",
|
|
19
|
+
"README.zh.md",
|
|
20
|
+
"LICENSE",
|
|
21
|
+
"AGENTS.md"
|
|
22
|
+
],
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@rayadesu/dsh-llm-billing": "file:./packages/llm-billing",
|
|
28
|
+
"@rayadesu/dsh-client-ui-billing": "file:./packages/ui-billing"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "pnpm -r build"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Bilingual-pair consistency record: the git blob hash of each side as of the
|
|
2
|
+
# last confirmed-consistent state. Both languages carry equal authority; after
|
|
3
|
+
# editing either side, bring the other along and re-record both hashes with:
|
|
4
|
+
# git hash-object README.md README.zh.md
|
|
5
|
+
README.md: 655288ebdb37cee4ecd3edfad8b3953e3a4e87ee
|
|
6
|
+
README.zh.md: e8ac4a2716ffe57200bb9757e1f0c6dabaf77c2f
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @rayadesu/dsh-llm-billing
|
|
2
|
+
|
|
3
|
+
English | [中文](README.zh.md)
|
|
4
|
+
|
|
5
|
+
Standalone host plugin that turns the DeepSeek account balance and per-session spend into a `billing` Remote. It owns the `/user/balance` transport, the peak/off-peak pricing table, and the per-session spend pricing, so a deployment can surface "how much is left, and what this session cost" without coupling that to the chat-completions adapter. The browser half is [`dsh-client-ui-billing`](../ui-billing/README.md).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Add the plugin to a composition (a `cordis.yml` row) and give it a credential. It resolves the API key from the credential seam (or the environment variable named by `apiKeyEnv`) and the endpoint from `baseURL`, then `$DEEPSEEK_BASE_URL`, then the public API.
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
- id: llm-billing
|
|
13
|
+
name: '@rayadesu/dsh-llm-billing'
|
|
14
|
+
config:
|
|
15
|
+
# apiKeyEnv: DEEPSEEK_API_KEY # default
|
|
16
|
+
# baseURL: https://api.deepseek.com
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The plugin registers the `billing` Remote with three methods: `getBalance()` (the parsed `/user/balance` snapshot), `getSessionSpend(sessionId)` (one session's billed cost), and `getTodaySpend()` (every session's billed cost on the current Beijing-time calendar day). The spend prices each `assistant/message` event's billed tokens (cache-hit input, cache-miss input including cache writes, and output including reasoning) at the official rate of the event's own Beijing-time peak/off-peak hour, then sums per model.
|
|
20
|
+
|
|
21
|
+
## Configuration
|
|
22
|
+
|
|
23
|
+
| Field | Default | Meaning |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| `apiKeyEnv` | `DEEPSEEK_API_KEY` | Credential-reference (environment-variable) name resolved per call. |
|
|
26
|
+
| `baseURL` | `$DEEPSEEK_BASE_URL` then `https://api.deepseek.com` | Endpoint base; `/user/balance` is appended. |
|
|
27
|
+
| `models` | V4 Flash + V4 Pro + V4 Flash Vision Exp | Advisory display rows, in presentation order. |
|
|
28
|
+
| `billing.peakHours` | 09:00–12:00, 14:00–18:00 (Beijing) | Peak-hour windows; all other hours are off-peak. |
|
|
29
|
+
| `billing.models` | Published V4 rates | Per-model peak/off-peak price rows (`cacheHitInput`, `cacheMissInput`, `output`, in CNY per 1M tokens). |
|
|
30
|
+
|
|
31
|
+
Override one model without dropping the others by supplying a non-empty `billing.models` list; an empty or omitted list falls back to the published defaults.
|
|
32
|
+
|
|
33
|
+
## Model Experience
|
|
34
|
+
|
|
35
|
+
None, as this package is a read-only Remote projection of provider and session facts and touches no prompt, message, schema, stream, or tool result.
|
|
36
|
+
|
|
37
|
+
#### KV Cache effect
|
|
38
|
+
|
|
39
|
+
None; its only provider call is a credential-authenticated `/user/balance` read, which is not cached in the provider KV store.
|
|
40
|
+
|
|
41
|
+
## Known Limitations and Deferred Work
|
|
42
|
+
|
|
43
|
+
- **Priced rows only** — the session and today spends only price models that have a `billing.models` row; a model without a rate row is omitted.
|
|
44
|
+
- **On-demand read** — the session spend reads the session's full event log on each call rather than maintaining an incremental aggregate, so cost grows with the per-session log size; `getTodaySpend()` reads every session's log, and a session whose log cannot be read is skipped with a warning instead of failing the whole day's total.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @rayadesu/dsh-llm-billing
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 中文
|
|
4
|
+
|
|
5
|
+
独立的宿主插件,把 DeepSeek 账户余额与会话花费变成 `billing` Remote。它拥有 `/user/balance` 传输、峰谷计价表与每会话的计费花费计价,因此部署可以在不把这个能力与聊天补全适配器耦合的前提下,展示「还剩多少、这个会话花了多少」。浏览器侧是 [`dsh-client-ui-billing`](../ui-billing/README.md)。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
把插件加进组合(一个 `cordis.yml` 行)并给它一个凭据。它先从凭据 seam(或 `apiKeyEnv` 指定的环境变量)解析 API key,再从 `baseURL`、其次 `$DEEPSEEK_BASE_URL`、最后公共 API 解析端点。
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
- id: llm-billing
|
|
13
|
+
name: '@rayadesu/dsh-llm-billing'
|
|
14
|
+
config:
|
|
15
|
+
# apiKeyEnv: DEEPSEEK_API_KEY # default
|
|
16
|
+
# baseURL: https://api.deepseek.com
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
插件注册 `billing` Remote,含三个方法:`getBalance()`(解析后的 `/user/balance` 快照)、`getSessionSpend(sessionId)`(单个会话的计费花费)与 `getTodaySpend()`(当前北京时间自然日内所有会话的计费花费合计)。会话花费把每条 `assistant/message` 事件的计费 token(缓存命中输入、含缓存写入的未命中输入、含推理的输出)按事件自身发生时刻(北京时间)所在的峰/谷单价计价,再按模型汇总。
|
|
20
|
+
|
|
21
|
+
## 配置
|
|
22
|
+
|
|
23
|
+
| 字段 | 默认 | 含义 |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| `apiKeyEnv` | `DEEPSEEK_API_KEY` | 每次调用时解析的凭据引用(环境变量)名。 |
|
|
26
|
+
| `baseURL` | `$DEEPSEEK_BASE_URL`,其次 `https://api.deepseek.com` | 端点基础地址;会追加 `/user/balance`。 |
|
|
27
|
+
| `models` | V4 Flash + V4 Pro + V4 Flash Vision Exp | 展示用的模型行,按展示顺序。 |
|
|
28
|
+
| `billing.peakHours` | 09:00–12:00、14:00–18:00(北京) | 高峰时段窗口;其余时段为低谷。 |
|
|
29
|
+
| `billing.models` | 官方 V4 费率 | 每个模型的峰/谷单价行(`cacheHitInput`、`cacheMissInput`、`output`,单位:元/百万 token)。 |
|
|
30
|
+
|
|
31
|
+
只想覆盖某个模型而不丢其它,就提供一个非空的 `billing.models` 列表;空或省略则回退到官方默认费率。
|
|
32
|
+
|
|
33
|
+
## 模型体验
|
|
34
|
+
|
|
35
|
+
无,因为本包是 provider 与会话事实的只读 Remote 投影,不触及 prompt、消息、schema、流或工具结果。
|
|
36
|
+
|
|
37
|
+
#### KV Cache effect
|
|
38
|
+
|
|
39
|
+
无;它唯一的 provider 调用是一次带凭据的 `/user/balance` 读取,不落在 provider 的 KV 缓存里。
|
|
40
|
+
|
|
41
|
+
## 已知限制与暂缓事项
|
|
42
|
+
|
|
43
|
+
- **有费率行才计价** —— 会话花费与今日花费只统计价目表(`billing.models`)里有的模型;没有费率行的模型不计入。
|
|
44
|
+
- **按需读取** —— 会话花费在每次调用时读取该会话的完整事件日志,而非维护增量聚合,因此成本随单会话日志大小增长;`getTodaySpend()` 会读取每个会话的日志,日志无法读取的会话带警告跳过,而不是让整日合计失败。
|