@rayadesu/dsh-billing 0.3.8 → 0.3.10
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 +8 -1
- package/README.i18n.yaml +2 -2
- package/README.md +12 -11
- package/README.zh.md +12 -11
- package/package.json +8 -3
package/AGENTS.md
CHANGED
|
@@ -47,7 +47,7 @@ cordis.patch.yml DSH profile bundle 补丁层:挂载 llm-billing + ui-
|
|
|
47
47
|
- **密钥不进仓库**:`DEEPSEEK_API_KEY` 等一律由用户环境或凭据 seam 提供,仓库不含真实值。
|
|
48
48
|
- **README 双语**:每个 README 遵循 DSH 结构 `README.md`(EN) + `README.zh.md`(ZH) +
|
|
49
49
|
`README.i18n.yaml`(记录两文件 git blob hash,改动后需更新)。
|
|
50
|
-
- **版本对齐**:根 bundle 与两个包统一版本号(当前 0.3.
|
|
50
|
+
- **版本对齐**:根 bundle 与两个包统一版本号(当前 0.3.10),`pnpm-lock.yaml` 随依赖变更更新。
|
|
51
51
|
- **文本规范**:LF 换行、文件末尾一个换行(`.editorconfig`/`.gitattributes` 已声明)。
|
|
52
52
|
|
|
53
53
|
## 常用命令
|
|
@@ -60,4 +60,11 @@ pnpm run verify # 发布前校验
|
|
|
60
60
|
dsh plugin --profile web add @rayadesu/dsh-billing @rayadesu/dsh-llm-billing @rayadesu/dsh-client-ui-billing # 安装进 DSH
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
+
**从零构建顺序是硬约束**:`ui-billing` 的浏览器半面(`tsconfig.client.json`)导入
|
|
64
|
+
`@rayadesu/dsh-llm-billing/remote`,其类型声明是 host 面 tsdown 生成的
|
|
65
|
+
`lib/typert.remote-client.d.ts`(gitignore,不入库)。所以干净 checkout 必须先跑
|
|
66
|
+
`pnpm run build:host`(tsc + tsdown 生成 typert 产物)再跑
|
|
67
|
+
`pnpm run typecheck` / `pnpm run build:client`;`pnpm run build` 本身已按
|
|
68
|
+
host → client 顺序封装,CI 亦按此顺序执行。
|
|
69
|
+
|
|
63
70
|
改动后至少校验 JSON/YAML 可解析,并更新受影响包的 README(双语都要)。
|
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# last confirmed-consistent state. Both languages carry equal authority; after
|
|
3
3
|
# editing either side, bring the other along and re-record both hashes with:
|
|
4
4
|
# git hash-object README.md README.zh.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: c83e7559af62aba5c8ceb4dfffc18de50138f333
|
|
6
|
+
README.zh.md: 01127599e394e374adcb77a4109ad4b70c123801
|
package/README.md
CHANGED
|
@@ -15,8 +15,8 @@ A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) plugin tha
|
|
|
15
15
|
|
|
16
16
|
## Data update mechanics
|
|
17
17
|
|
|
18
|
-
- **Session spend follows the conversation** —
|
|
19
|
-
- **Balance
|
|
18
|
+
- **Session spend follows the conversation** — the host prices every committed event into a per-session projection (`billingTodaySpend`) and pushes it to the browser, so **this session's spend** updates live with no Remote call; the Remote read remains the fallback when the projection registry is absent. **Today's spend** is recomputed on turn settle (one shared scan serves both the aggregate and the ranking), and each turn's cost comes from **one batch fetch per session** instead of one call per rendered message.
|
|
19
|
+
- **Balance is cached, not polled** — the host reuses one `/user/balance` snapshot for 15 seconds (manual refresh forces a fresh one) and caps each request at 5 seconds; the browser keeps the last settled value so a session switch renders the amount immediately and revalidates in the background. There is still no polling.
|
|
20
20
|
- **Old values survive refreshes** — a failed refresh keeps the last good value instead of blanking it.
|
|
21
21
|
|
|
22
22
|
## Preview
|
|
@@ -38,7 +38,7 @@ Close-up of the turn-cost amount — the static `¥` amount at the end of the ac
|
|
|
38
38
|
|
|
39
39
|
| Package | Side | Role |
|
|
40
40
|
| --- | --- | --- |
|
|
41
|
-
| [`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`, `getTodaySessionsSpend`, `getTurnSpend`). |
|
|
41
|
+
| [`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(force?)`, `getSessionSpend`, `getTodaySpend`, `getTodaySessionsSpend`, `getTurnSpend`, `getSessionTurnSpends`) and registers the client-visible `billingTodaySpend` projection unit. |
|
|
42
42
|
| [`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, plus the static turn-cost amount at the end of the message actions strip. |
|
|
43
43
|
|
|
44
44
|
## Prerequisites
|
|
@@ -236,26 +236,27 @@ Both packages ship sane defaults; everything below is optional.
|
|
|
236
236
|
| --- | --- | --- |
|
|
237
237
|
| `apiKeyEnv` | `DEEPSEEK_API_KEY` | Credential-reference (environment-variable) name resolved per call. |
|
|
238
238
|
| `baseURL` | `$DEEPSEEK_BASE_URL` then `https://api.deepseek.com` | Endpoint base; `/user/balance` is appended. |
|
|
239
|
-
| `models` | V4 Flash + V4 Pro + V4 Flash Vision Exp | Advisory display rows, in presentation order. |
|
|
239
|
+
| `models` | V4.1 Flash (`deepseek-flash`) + V4 Flash + V4 Pro + V4 Flash Vision Exp + MiMo-V2.5 series | Advisory display rows, in presentation order; they mirror DSH's `llm-deepseek` catalog. |
|
|
240
240
|
| `billing.peakHours` | 09:00–12:00, 14:00–18:00 (Beijing, weekdays) | Peak-hour windows, applied weekdays (Mon–Fri) only; weekends and all other hours are off-peak. |
|
|
241
|
-
| `billing.models` | Published V4 rates | Per-model
|
|
241
|
+
| `billing.models` | Published V4 + MiMo rates | Per-model price rows (`cacheHitInput`, `cacheMissInput`, `output`, in CNY per 1M tokens) with an optional inclusive `effectiveFrom`; several rows sharing a model are its rate revisions. |
|
|
242
242
|
|
|
243
243
|
## How session spend is computed
|
|
244
244
|
|
|
245
|
-
- Each `assistant/message` event reports three billed token buckets: **cache-hit input**, **cache-miss input** (uncached input + cache writes), and **output** (including reasoning).
|
|
246
|
-
- Each
|
|
245
|
+
- Each `assistant/message` event reports three billed token buckets: **cache-hit input**, **cache-miss input** (uncached input + cache writes), and **output** (including reasoning). A failed or retried `assistant/attempt` reports its usage only in its embedded stream; that sample is priced too (with the model of the latest `request/header`), a later sample for the same `(turn, step)` **replaces** the earlier one, and `llm/retry-started` makes the retried attempt **add** — the same accounting DSH's own turn-usage disclosure uses.
|
|
246
|
+
- Each sample is priced at the peak/off-peak rate of its own **Beijing-time** hour — and of the rate revision in effect at its own timestamp — the three buckets are billed separately (`缓存命中 ¥X · 未命中输入 ¥Y · 输出 ¥Z`), then summed per model. Peak windows apply weekdays (Monday–Friday) only; weekends are always off-peak.
|
|
247
247
|
- **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.
|
|
248
|
-
- **Turn cost** prices the
|
|
248
|
+
- **Turn cost** prices the events inside the turn's `turn/start`..`turn/end` range with the same rules (located by the closing message's session id + message id), folded in one pass for the whole session and served as a `messageId → cost` map.
|
|
249
249
|
- **Today session ranking** aggregates today's spend per session with the same rules (a cross-day session counts only today's part), sorted descending; names come from the log's latest `session/title` event (the auto-generated Chinese title or a user rename).
|
|
250
|
-
- Models without a rate row are not priced (the built-in
|
|
250
|
+
- Models without a rate row are not priced (the built-in table covers the DSH `llm-deepseek` catalog — V4.1 Flash `deepseek-flash`, V4 Flash, V4 Pro, V4 Flash Vision Exp — plus the retired `deepseek-v4.1-flash-expires-on-0910` preview id and the MiMo-V2.5 series; every flash-series route shares the same pair). Each sample takes the rate revision in effect at its own timestamp: the base schedule is the DeepSeek pricing effective **August 17**; the **flash series** (V4.1 Flash, V4 Flash, V4 Flash Vision Exp, and the retired id) was re-priced effective **September 10, 12:00 Beijing time** to off-peak 0.02 / 1.0 / 4.0 CNY per 1M tokens with peak at twice those prices — samples from before that instant, the V4.1 Flash route's own earlier usage included, keep the superseded rates; the **V4 Pro** route is announced to switch to V4.1 Flash and its rates on **September 14, 12:00 Beijing time**; the MiMo-V2.5 series is untouched. The weekend-off-peak rule (weekends billed at off-peak prices all day) follows the adjustment effective **August 23**.
|
|
251
251
|
|
|
252
252
|
## Known limitations
|
|
253
253
|
|
|
254
254
|
- **Priced rows only** — the session, turn, and today spends only price models that have a `billing.models` row.
|
|
255
|
-
- **On-demand aggregation** — today's spend and the session ranking are computed on the host behind a 60-second cache; a miss
|
|
255
|
+
- **On-demand aggregation** — today's spend and the session ranking are computed on the host behind a 60-second cache and share ONE scan; a miss resolves live sessions from their eager projection cells and cold sessions from the zero-I/O projection-cache row when that row's own day is not the queried one, reading a log only for sessions whose persisted revision changed (or whose cached row covers the queried day). A failed resolution is remembered by revision instead of being retried every scan.
|
|
256
|
+
- **Ranking is fetched on demand** — the panel loads the ranking when it is opened (and on refresh), so a badge that stays closed never pays for the all-session scan.
|
|
256
257
|
- **Ranking capped at 10** — the panel shows at most the top 10 sessions, with a "…N more sessions" hint.
|
|
257
258
|
- **Turn cost needs a finalized closing message** — interrupted turns have no actions row, so no turn cost; cold sessions served straight from the projection cache may rank with an "Untitled" name until their log is read again.
|
|
258
|
-
- **Balance
|
|
259
|
+
- **Balance is TTL-cached** — the host reuses one snapshot for up to 15 seconds and each request aborts after 5 seconds; spending from another client does not move the shown value until the TTL expires, a manual refresh, or a browser reload (there is no polling).
|
|
259
260
|
- **Estimate, not a promise** — the session spend prices tokens at official rates; the provider's actual billing prevails.
|
|
260
261
|
|
|
261
262
|
## License
|
package/README.zh.md
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
|
|
16
16
|
## 数据更新机制
|
|
17
17
|
|
|
18
|
-
- **会话花费自动跟随** ——
|
|
19
|
-
-
|
|
18
|
+
- **会话花费自动跟随** —— 主机端把每条已提交事件计价进每会话投影(`billingTodaySpend`)并推送给浏览器,**本会话花费**因此零 Remote 调用、实时更新;投影注册表不存在时回退到 Remote 读取。**今日共花费**在回合结束时重算(聚合与排行共用同一次扫描),每条消息的行尾金额来自**每会话一次批量拉取**,不再逐条消息各发一次请求。
|
|
19
|
+
- **额度有缓存、但不轮询** —— 主机端 15 秒内复用同一份 `/user/balance` 快照(手动刷新强制取新),单次请求 5 秒超时;浏览器保留最后一次结果,切会话时立即渲染旧值并在后台校验。仍然**没有轮询**。
|
|
20
20
|
- **刷新期间旧值保留** —— 刷新失败保留上一次有效值,不会清空。
|
|
21
21
|
|
|
22
22
|
## 显示样式
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
| 包 | 侧 | 作用 |
|
|
40
40
|
| --- | --- | --- |
|
|
41
|
-
| [`packages/llm-billing`](packages/llm-billing) —— `@rayadesu/dsh-llm-billing` | 主机端 | 负责 `/user/balance` 传输与峰/谷计价表。对外暴露 `billing` Remote(`getBalance`、`getSessionSpend`、`getTodaySpend`、`getTodaySessionsSpend`、`getTurnSpend
|
|
41
|
+
| [`packages/llm-billing`](packages/llm-billing) —— `@rayadesu/dsh-llm-billing` | 主机端 | 负责 `/user/balance` 传输与峰/谷计价表。对外暴露 `billing` Remote(`getBalance(force?)`、`getSessionSpend`、`getTodaySpend`、`getTodaySessionsSpend`、`getTurnSpend`、`getSessionTurnSpends`),并注册客户端可见的 `billingTodaySpend` 投影单元。 |
|
|
42
42
|
| [`packages/ui-billing`](packages/ui-billing) —— `@rayadesu/dsh-client-ui-billing` | 浏览器端 | 自己挂载 `billing` Remote,并贡献会话头部徽标与详情面板、消息操作行行尾的静态本轮花费金额。 |
|
|
43
43
|
|
|
44
44
|
## 前置条件
|
|
@@ -212,26 +212,27 @@ npm publish # @rayadesu/dsh-billing bundle(仓库根)
|
|
|
212
212
|
| --- | --- | --- |
|
|
213
213
|
| `apiKeyEnv` | `DEEPSEEK_API_KEY` | 每次调用时解析的凭据引用(环境变量)名。 |
|
|
214
214
|
| `baseURL` | `$DEEPSEEK_BASE_URL`,其次 `https://api.deepseek.com` | 端点基础地址;会追加 `/user/balance`。 |
|
|
215
|
-
| `models` | V4 Flash + V4 Pro + V4 Flash Vision Exp |
|
|
215
|
+
| `models` | V4.1 Flash(`deepseek-flash`)+ V4 Flash + V4 Pro + V4 Flash Vision Exp + MiMo-V2.5 系列 | 展示用的模型行,按展示顺序;与 DSH `llm-deepseek` 目录对齐。 |
|
|
216
216
|
| `billing.peakHours` | 09:00–12:00、14:00–18:00(北京,仅工作日) | 高峰时段窗口,仅周一至周五适用;周末与其余时段均为低谷。 |
|
|
217
|
-
| `billing.models` | 官方 V4 费率 |
|
|
217
|
+
| `billing.models` | 官方 V4 + MiMo 费率 | 每个模型的单价行(`cacheHitInput`、`cacheMissInput`、`output`,单位:元/百万 token),可带生效时刻 `effectiveFrom`(含该时刻);同一模型的多行即其费率版本。 |
|
|
218
218
|
|
|
219
219
|
## 会话花费是怎么算的
|
|
220
220
|
|
|
221
|
-
- 每条 `assistant/message` 事件报告三个计费 token 桶:**缓存命中输入**、**未命中输入**(未缓存输入 +
|
|
222
|
-
-
|
|
221
|
+
- 每条 `assistant/message` 事件报告三个计费 token 桶:**缓存命中输入**、**未命中输入**(未缓存输入 + 缓存写入)、**输出**(含推理)。失败或重试的 `assistant/attempt` 只在自身内嵌 stream 里报告用量,这份样本同样计价(模型取最近一条 `request/header`);同一 `(turn, step)` 的后一份样本**替换**前一份,`llm/retry-started` 之后重试的那次**累加** —— 与 DSH 自己的回合用量口径一致。
|
|
222
|
+
- 每份样本按其**发生时刻**(北京时间)所在的峰/谷时段单价——以及该时刻生效的费率版本——计价,三个桶分别计费(`缓存命中 ¥X · 未命中输入 ¥Y · 输出 ¥Z`),再按模型汇总。高峰窗口仅周一至周五适用;周末全天按低谷价计费。
|
|
223
223
|
- **今日共花费**按同一个计价规则汇总当天(北京时间自然日)所有会话的事件;事件归属的日期同样按北京时间计算。
|
|
224
|
-
- **本轮花费**按同一规则计价该回合 `turn/start`..`turn/end`
|
|
224
|
+
- **本轮花费**按同一规则计价该回合 `turn/start`..`turn/end` 区间内的事件(定位到收尾消息的会话 id + 消息 id),整会话一趟折出 `messageId → 金额` 映射后下发。
|
|
225
225
|
- **今日会话花费排行**按同一规则按会话汇总今日花费(跨天会话只统计今天的部分),从高到低排序;会话名取日志中最后一条 `session/title` 事件(自动生成的中文标题或用户重命名的新标题)。
|
|
226
|
-
-
|
|
226
|
+
- 没有费率行的模型不计入(内置价目表覆盖 DSH `llm-deepseek` 目录——V4.1 Flash `deepseek-flash`、V4 Flash、V4 Pro、V4 Flash Vision Exp——外加已退役的 `deepseek-v4.1-flash-expires-on-0910` 预览 id 与 MiMo-V2.5 系列;flash 系列各路由同价)。每份样本取**自身时刻生效的费率版本**:基础价目为 DeepSeek **8 月 17 日实行**的费率;**flash 系列**(V4.1 Flash、V4 Flash、V4 Flash Vision Exp 及退役 id)自 **9 月 10 日 12:00(北京时间)** 起降为谷时 0.02 / 1.0 / 4.0 元每百万 token、峰时为其两倍——该时刻之前的样本(含 V4.1 Flash 路由自身的早先用量的)沿用被取代的旧价;**V4 Pro** 路由公告于 **9 月 14 日 12:00(北京时间)** 改由 V4.1 Flash 服务并按其实施费率计费;MiMo-V2.5 系列不受影响。**周末按低谷价计费**的规则按 **8 月 23 日**生效的调整执行。
|
|
227
227
|
|
|
228
228
|
## 已知限制
|
|
229
229
|
|
|
230
230
|
- **有费率行才计价** —— 会话花费、本轮花费与今日共花费只统计价目表(`billing.models`)里有的模型。
|
|
231
|
-
- **按需聚合** —— 今日共花费与今日会话排行在主机端 60
|
|
231
|
+
- **按需聚合** —— 今日共花费与今日会话排行在主机端 60 秒缓存之后计算,且共用同一次扫描;未命中时,活跃会话直接读投影单元,冷会话若缓存行自身的日期不是查询日则零 I/O 直接作答,只有持久化修订变化(或缓存行覆盖查询日)的会话才读日志。读取失败的会话按修订号记住,不再每轮重试。
|
|
232
|
+
- **排行按需拉取** —— 详情面板打开(或手动刷新)时才拉取排行,徽标一直关着就不会为全量会话扫描买单。
|
|
232
233
|
- **排行只显示前 10** —— 详情面板最多展示前 10 个会话,其余以「…还有 N 个会话」提示。
|
|
233
234
|
- **本轮花费只出现在已定稿的收尾消息** —— 中断的回合没有操作行,不显示本轮花费;冷会话(投影缓存直接命中)排行标题可能显示「未命名」,待其日志被重新读取后恢复。
|
|
234
|
-
-
|
|
235
|
+
- **额度带 TTL 缓存** —— 主机端最多复用 15 秒内的同一份快照,单次请求 5 秒超时;账户在其他客户端产生消耗时,界面值要等 TTL 过期、手动刷新或刷新浏览器才变(仍无轮询)。
|
|
235
236
|
- **是估算,不是承诺** —— 会话花费按官方单价对 token 计价;实际计费以服务商为准。
|
|
236
237
|
|
|
237
238
|
## 许可证
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rayadesu/dsh-billing",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.10",
|
|
4
4
|
"description": "DeepSeek Harness billing plugin: account balance and this session's billed spend with a session-header badge.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"build:host": "tsc -b tsconfig.host.json && tsdown --env.DSH_BUILD_FACE host",
|
|
22
22
|
"build:client": "tsc -b tsconfig.client.json && tsdown --env.DSH_BUILD_FACE client",
|
|
23
23
|
"typecheck": "tsc -b tsconfig.host.json && tsc -b tsconfig.client.json",
|
|
24
|
+
"lint": "eslint .",
|
|
24
25
|
"test": "vitest run",
|
|
25
26
|
"verify": "node scripts/verify-packages.mjs"
|
|
26
27
|
},
|
|
@@ -39,18 +40,22 @@
|
|
|
39
40
|
"access": "public"
|
|
40
41
|
},
|
|
41
42
|
"peerDependencies": {
|
|
42
|
-
"@rayadesu/dsh-client-ui-billing": "^0.3.
|
|
43
|
-
"@rayadesu/dsh-llm-billing": "^0.3.
|
|
43
|
+
"@rayadesu/dsh-client-ui-billing": "^0.3.10",
|
|
44
|
+
"@rayadesu/dsh-llm-billing": "^0.3.10"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
47
48
|
"@deepseek-ai/dsh-invariants": "^0.1.2-alpha.5",
|
|
48
49
|
"@deepseek-ai/dsh-typert-generator": "^0.1.2-alpha.5",
|
|
50
|
+
"@eslint/js": "^10.0.1",
|
|
49
51
|
"@types/node": "^22.20.0",
|
|
52
|
+
"eslint": "^10.9.1",
|
|
53
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
50
54
|
"jsdom": "29.1.1",
|
|
51
55
|
"lightningcss": "^1.32.0",
|
|
52
56
|
"tsdown": "^0.22.2",
|
|
53
57
|
"typescript": "^6.0.3",
|
|
58
|
+
"typescript-eslint": "^8.69.0",
|
|
54
59
|
"vitest": "^4.1.8"
|
|
55
60
|
}
|
|
56
61
|
}
|