dsh-model-billing 0.1.0 → 0.1.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.
- package/CHANGELOG.md +6 -0
- package/README.md +52 -6
- package/client.js +31 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="icon.svg" width="72" height="72" alt="dsh-model-billing icon">
|
|
2
|
+
<img src="https://unpkg.com/dsh-model-billing@0.1.0/icon.svg" width="72" height="72" alt="dsh-model-billing icon">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">dsh-model-billing</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">为 DeepSeek Harness Web GUI 调整模型顺序,并按轮次估算模型费用。</p>
|
|
8
8
|
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://www.npmjs.com/package/dsh-model-billing"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-model-billing.svg"></a>
|
|
11
|
+
<a href="https://github.com/likaileave/dsh-model-billing/releases"><img alt="GitHub release" src="https://img.shields.io/github/v/release/likaileave/dsh-model-billing"></a>
|
|
12
|
+
<a href="LICENSE"><img alt="License" src="https://img.shields.io/github/license/likaileave/dsh-model-billing"></a>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
9
15
|
<p align="center">
|
|
10
16
|
<a href="#中文">中文</a> · <a href="#english">English</a> · <a href="CHANGELOG.md">Changelog</a>
|
|
11
17
|
</p>
|
|
12
18
|
|
|
19
|
+
> **AI 生成声明**:本项目的代码、文档和图标由 AI 辅助生成,并经人工审核、修改和测试;发布者对最终发布内容负责。
|
|
20
|
+
>
|
|
21
|
+
> **AI-generated notice**: The code, documentation, and icon in this project were generated with AI assistance, then reviewed, modified, and tested by a human; the publisher is responsible for the released content.
|
|
22
|
+
|
|
13
23
|
## 中文
|
|
14
24
|
|
|
15
25
|
`dsh-model-billing` 是一个 DSH Web 客户端插件。它接管输入框右下角的模型选择器,让你按自己的顺序排列模型,并为每个模型维护三档 token 价格;会话过程中按实际 usage 估算每一轮和整个会话的费用。
|
|
@@ -19,7 +29,7 @@
|
|
|
19
29
|
- **自定义模型顺序**:在“设置 → 模型与费用”中用 ↑ / ↓ 调整已配置模型的顺序。模型选择器按这个顺序展示,跨提供方也保持你排的顺序,并用提供方名称分组。
|
|
20
30
|
- **三档 token 价格**:每个非 DeepSeek 模型可填写每百万 tokens 的缓存命中输入、缓存未命中输入、输出价格。`0` 是有效价格,留空表示未设置。
|
|
21
31
|
- **DeepSeek 官方价内置**:`deepseek-flash` 和 `deepseek-v4-pro` 直接使用 DeepSeek 官网的峰谷价,只读展示,不需要填写。
|
|
22
|
-
-
|
|
32
|
+
- **逐轮费用与使用模型**:每轮结束后在轮尾显示这一轮使用的模型,以及该轮费用和缓存命中率。
|
|
23
33
|
- **本会话费用**:输入框下方显示本会话累计估算、最近一轮费用和缓存命中率;展开后可查看按轮次和按模型的明细。
|
|
24
34
|
- **DeepSeek 也计入金额**:每条 usage 按事件发生时的北京时间自动选择高峰或空闲价,与第三方模型一起进入统计。
|
|
25
35
|
|
|
@@ -56,7 +66,13 @@ DeepSeek 价格只读,不写入本地价格配置。官网调价或节假日
|
|
|
56
66
|
|
|
57
67
|
### 安装
|
|
58
68
|
|
|
59
|
-
|
|
69
|
+
**npm**
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
dsh plugin --profile desktop add dsh-model-billing
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**从 dsh-market 安装**
|
|
60
76
|
|
|
61
77
|
在 dsh-market 中搜索 `dsh-model-billing` 安装。
|
|
62
78
|
|
|
@@ -80,6 +96,15 @@ dsh plugin --profile desktop add ./dsh-model-billing
|
|
|
80
96
|
|
|
81
97
|
安装或更新后刷新 Web 页面。设置页位于“模型与费用”。
|
|
82
98
|
|
|
99
|
+
### 发布
|
|
100
|
+
|
|
101
|
+
npm 包和 GitHub Release 使用相同版本号,两个渠道分别发布:
|
|
102
|
+
|
|
103
|
+
- npm:<https://www.npmjs.com/package/dsh-model-billing>
|
|
104
|
+
- GitHub Releases:<https://github.com/likaileave/dsh-model-billing/releases>
|
|
105
|
+
|
|
106
|
+
两个渠道是并列的发布渠道,不承诺自动同步。
|
|
107
|
+
|
|
83
108
|
### 数据位置
|
|
84
109
|
|
|
85
110
|
模型顺序和价格保存在:
|
|
@@ -123,7 +148,7 @@ node --test test/host.test.mjs test/routes.test.mjs
|
|
|
123
148
|
- **Custom model order** in Settings → Models & Cost; the composer picker follows that order across providers and groups models by provider.
|
|
124
149
|
- **Three prices per model**: cache-hit input, cache-miss input, and output, in CNY per million tokens. `0` is a valid price; blank means unset.
|
|
125
150
|
- **Built-in official DeepSeek pricing** for `deepseek-flash` and `deepseek-v4-pro`, selected per usage event between peak and off-peak Beijing time.
|
|
126
|
-
- **Per-turn amount** at the end of each turn.
|
|
151
|
+
- **Per-turn model and amount** at the end of each turn, together with the turn's cache-hit rate.
|
|
127
152
|
- **Session summary** below the composer plus a detail panel grouped by turn and by model.
|
|
128
153
|
- **DeepSeek is billed too**, using the same three-price formula and the event's timestamp.
|
|
129
154
|
|
|
@@ -141,13 +166,25 @@ The plugin ships **no third-party price defaults**. Enter your provider's actual
|
|
|
141
166
|
|
|
142
167
|
### Install
|
|
143
168
|
|
|
144
|
-
|
|
169
|
+
**npm**
|
|
170
|
+
|
|
171
|
+
```sh
|
|
172
|
+
dsh plugin --profile desktop add dsh-model-billing
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**From dsh-market**
|
|
176
|
+
|
|
177
|
+
Search for `dsh-model-billing` in dsh-market.
|
|
178
|
+
|
|
179
|
+
**From a GitHub Release**
|
|
180
|
+
|
|
181
|
+
Download `dsh-model-billing.tgz` from [Releases](https://github.com/likaileave/dsh-model-billing/releases), then:
|
|
145
182
|
|
|
146
183
|
```sh
|
|
147
184
|
dsh plugin --profile desktop add ./dsh-model-billing.tgz
|
|
148
185
|
```
|
|
149
186
|
|
|
150
|
-
From a checkout
|
|
187
|
+
**From a checkout**
|
|
151
188
|
|
|
152
189
|
```sh
|
|
153
190
|
git clone https://github.com/likaileave/dsh-model-billing.git
|
|
@@ -156,6 +193,15 @@ dsh plugin --profile desktop add ./dsh-model-billing
|
|
|
156
193
|
|
|
157
194
|
Refresh the Web page after installing or updating.
|
|
158
195
|
|
|
196
|
+
### Release channels
|
|
197
|
+
|
|
198
|
+
The npm package and the GitHub Release use the same version number and are published separately:
|
|
199
|
+
|
|
200
|
+
- npm: <https://www.npmjs.com/package/dsh-model-billing>
|
|
201
|
+
- GitHub Releases: <https://github.com/likaileave/dsh-model-billing/releases>
|
|
202
|
+
|
|
203
|
+
They are parallel distribution channels, not an automatic mirror.
|
|
204
|
+
|
|
159
205
|
### Data
|
|
160
206
|
|
|
161
207
|
Order and prices live in `~/.dsh/model-billing.json` (or `$DSH_HOME/model-billing.json`). Writes use a temporary file plus atomic replace.
|
package/client.js
CHANGED
|
@@ -78,6 +78,8 @@ window.__ModuleLoader__.load({
|
|
|
78
78
|
partialShort: '部分未定价',
|
|
79
79
|
partialNote: '有非 DeepSeek 调用尚未配置完整价格,合计只包含已定价部分。',
|
|
80
80
|
estimateNote: '金额由会话日志中的 token 用量和缓存命中估算;DeepSeek 按事件时间使用内置峰谷价,实际账单以提供方为准。',
|
|
81
|
+
turnModelTitle: '本轮实际调用的模型(多个模型按名称排序)',
|
|
82
|
+
listSep: '、',
|
|
81
83
|
turnCost: '费用',
|
|
82
84
|
turnCostTitle: '根据本轮 token 用量、缓存命中与价格估算',
|
|
83
85
|
chooseModel: '选择模型',
|
|
@@ -150,6 +152,8 @@ window.__ModuleLoader__.load({
|
|
|
150
152
|
partialShort: 'partly unpriced',
|
|
151
153
|
partialNote: 'Some non-DeepSeek calls do not have a complete price set; the total includes only priced calls.',
|
|
152
154
|
estimateNote: 'Amounts are estimated from token usage and cache hits in the session log; DeepSeek uses built-in peak/off-peak prices at the event time, and the provider bill is authoritative.',
|
|
155
|
+
turnModelTitle: 'Models actually called this turn (multiple models sorted by name)',
|
|
156
|
+
listSep: ', ',
|
|
153
157
|
turnCost: 'Cost',
|
|
154
158
|
turnCostTitle: 'Estimated from this turn’s tokens, cache hits and prices',
|
|
155
159
|
chooseModel: 'Select model',
|
|
@@ -1030,20 +1034,42 @@ window.__ModuleLoader__.load({
|
|
|
1030
1034
|
// Per-turn cost chip
|
|
1031
1035
|
// ---------------------------------------------------------------------
|
|
1032
1036
|
|
|
1033
|
-
function
|
|
1037
|
+
function turnModelText(models, translate) {
|
|
1038
|
+
const names = (models ?? []).map((entry) => {
|
|
1039
|
+
if (entry === undefined || entry === null) return null
|
|
1040
|
+
if (typeof entry.name === 'string' && entry.name !== '') return entry.name
|
|
1041
|
+
return entry.provider !== undefined && entry.model !== undefined
|
|
1042
|
+
? `${entry.provider} / ${entry.model}`
|
|
1043
|
+
: null
|
|
1044
|
+
}).filter((name) => name !== null)
|
|
1045
|
+
if (names.length === 0) return null
|
|
1046
|
+
return names.join(translate('listSep'))
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
function TurnCost(props) {
|
|
1050
|
+
const { turn } = props
|
|
1051
|
+
// The turnTail owner hands over the whole folded turn life cycle, not just its number.
|
|
1052
|
+
const turnNumber = turn === null || turn === undefined
|
|
1053
|
+
? undefined
|
|
1054
|
+
: typeof turn === 'number' ? turn : turn.turn
|
|
1055
|
+
const sessionId = props.sessionId
|
|
1056
|
+
const useProjection = props.useProjection
|
|
1034
1057
|
const translate = useT()
|
|
1035
|
-
const tokenUsage = useProjection('tokenUsage')
|
|
1058
|
+
const tokenUsage = typeof useProjection === 'function' ? useProjection('tokenUsage') : undefined
|
|
1036
1059
|
const revision = tokenUsageRevision(tokenUsage)
|
|
1037
1060
|
const usage = useSessionUsage(sessionId, revision)
|
|
1038
|
-
const
|
|
1039
|
-
|
|
1061
|
+
const rows = usage.data?.turns
|
|
1062
|
+
const row = rows?.find((entry) => entry.turn === turnNumber)
|
|
1063
|
+
if (row === undefined) return null
|
|
1040
1064
|
const costText = row.costKnown
|
|
1041
1065
|
? `≈ ${formatMoney(row.cost)}`
|
|
1042
1066
|
: row.pricedAttempts > 0 ? `≈ ${formatMoney(row.cost)}*` : translate('pricePlaceholder')
|
|
1067
|
+
const modelText = turnModelText(row.models, translate)
|
|
1043
1068
|
return h('span', {
|
|
1044
1069
|
className: 'mb-turn',
|
|
1045
|
-
title: translate('turnCostTitle')
|
|
1070
|
+
title: `${translate('turnModelTitle')}\n${translate('turnCostTitle')}`,
|
|
1046
1071
|
},
|
|
1072
|
+
modelText === null ? null : h(Fragment, null, translate('model'), ' ', h('strong', null, modelText), ' · '),
|
|
1047
1073
|
translate('turnCost'), ' ', h('strong', null, costText),
|
|
1048
1074
|
row.cacheHit === null ? null : ` · ${translate('cacheHit')} ${formatPercent(row.cacheHit)}`,
|
|
1049
1075
|
row.partial ? ` · ${translate('partialShort')}` : '')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-model-billing",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Reorder models in the DSH composer picker, store three per-million-token prices, and estimate per-turn and session cost with built-in DeepSeek peak/off-peak rates.",
|
|
6
6
|
"keywords": [
|