@dougen/dsh-deepseek-usage 0.11.1 → 0.12.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
@@ -3,7 +3,7 @@
3
3
  <!-- 渲染器会给标题 id 加 `user-content-` 前缀(npm 页面、GitHub 都是),跳转链接要用带前缀的锚点 -->
4
4
  [中文文档](#user-content-中文文档)
5
5
 
6
- A sidebar plugin for the **DeepSeek Harness (DSH) Web UI** that answers two questions without leaving the app: **how much balance is left**, and **what the model costs right now**.
6
+ A sidebar plugin for the **DeepSeek Harness (DSH) Web UI** that answers two questions without leaving the app: **how much balance is left**, and **what the model costs right now** — the second one for official DeepSeek models, whose prices the built-in table and DeepSeek's peak/off-peak windows cover.
7
7
 
8
8
  ![DeepSeek usage card / 用量卡片](https://cdn.jsdelivr.net/npm/@dougen/dsh-deepseek-usage/screenshot.png)
9
9
 
@@ -12,6 +12,7 @@ A sidebar plugin for the **DeepSeek Harness (DSH) Web UI** that answers two ques
12
12
  - **Balance** in the sidebar footer: your DeepSeek account balance (the symbol follows the account currency: `¥` / `$`).
13
13
  - **Unit prices of the active model**: input / input cache / output for the billing window in effect right now. They change when you switch models and when the peak/off-peak window flips.
14
14
  - **Peak / off-peak dot with a countdown**: orange during peak hours (Mon–Fri, excluding Chinese public holidays, 9:00–12:00 and 14:00–18:00 Beijing Time), green otherwise — weekends, public holidays and the make-up workdays that fall on a weekend are all off-peak; next to it, the time left until the next switch (`2d 15h`, `5h 47m`, `23m`).
15
+ - **Unit prices and the peak/off-peak dot are for official DeepSeek models only.** When the active model is not one of them (a third-party provider's model, or a router that reports the provider name as the model), the card shows the balance alone: the built-in price table and DeepSeek's peak/off-peak windows do not apply, so any figure derived from them would not match your bill.
15
16
  - Refreshes every 30 seconds, and immediately when you click the card or switch models. Follows the app light/dark theme and the DSH language (Chinese / English).
16
17
 
17
18
  ## DSH compatibility
@@ -50,7 +51,8 @@ The card then shows the reason instead of numbers:
50
51
  ### Prices differ from the official page
51
52
 
52
53
  - Prices are the built-in table `PRICE_TABLE` in `lib/pricing.js`, a snapshot of the official pricing page. It changes only when a new version of the plugin ships — there is no local price file and no background sync.
53
- - If the active model is not in the table, the card falls back to `deepseek-chat` pricing.
54
+ - The card only shows unit prices and the peak/off-peak dot when the active model is an official DeepSeek model (`deepseek-flash`, `deepseek-v4-pro`, `deepseek-chat`, `deepseek-reasoner` and the legacy names). Any other model — a third-party provider's, or a router reporting the provider name as the model — has no official peak/off-peak pricing, so the card hides both instead of showing a figure that would not match your bill.
55
+ - An official model newer than this plugin release is not in the table either, and the card hides prices for it until the table is updated.
54
56
  - Off-peak days come from the holiday table `HOLIDAY_RANGES` in `lib/pricing.js`. The State Council usually publishes next year's arrangement in November; update it then. Until you do, holidays are treated as ordinary workdays and the card shows peak prices during them.
55
57
 
56
58
  ## How it works
@@ -62,13 +64,14 @@ The card then shows the reason instead of numbers:
62
64
 
63
65
  ## 中文文档
64
66
 
65
- 一个 **DeepSeek Harness(DSH)网页界面**的侧边栏插件:不离开 DSH 就能知道**账号还剩多少钱**、**当前的模型现在什么价**。
67
+ 一个 **DeepSeek Harness(DSH)网页界面**的侧边栏插件:不离开 DSH 就能知道**账号还剩多少钱**;当前用的是 DeepSeek 官方模型时,还能看到**它现在什么价**——内置价格表与官方峰谷时段覆盖的正是这些模型。
66
68
 
67
69
  ### 这个插件做什么
68
70
 
69
71
  - **余额**:侧边栏底部显示 DeepSeek 账号余额(符号随账号币种 `¥` / `$`)。
70
72
  - **当前模型的档单价**:输入 / 输入缓存 / 输出,按此刻生效的计费时段显示;切换模型、跨过峰谷切换点时会跟着变。
71
73
  - **峰谷指示灯 + 倒计时**:高峰(周一至周五、不含中国法定节假日,9:00–12:00、14:00–18:00 北京时间)橙色,其余时间绿色——周末、法定节假日全天,以及调休上班的周末都是空闲;指示灯旁给出距下次切换的剩余时间(`2d 15h`、`5h 47m`、`23m`)。
74
+ - **档单价与峰谷指示灯只对 DeepSeek 官方模型显示**。当前模型不是官方模型时(第三方供应商的模型,或路由器把供应商名当模型名上报),卡片只显示余额:内置价格表与官方峰谷时段对它不成立,据此算出的数字与实际账单不符。
72
75
  - 每 30 秒自动刷新;点击卡片或切换模型时立即刷新。跟随应用明暗主题与 DSH 语言(中文 / English)。
73
76
 
74
77
  ### DSH 版本对应关系
@@ -105,7 +108,8 @@ dsh plugin --profile web remove @dougen/dsh-deepseek-usage
105
108
  价格与官方不一致时:
106
109
 
107
110
  - 价格是 `lib/pricing.js` 的内置表 `PRICE_TABLE`(官方价格页的快照),只在发布新版本时更新——没有本地价格文件,也没有后台同步。
108
- - 当前模型不在价格表里时,按 `deepseek-chat` 的价格显示。
111
+ - 只有当前模型是 DeepSeek 官方模型(`deepseek-flash`、`deepseek-v4-pro`、`deepseek-chat`、`deepseek-reasoner` 及旧名)时,卡片才显示档单价与峰谷指示灯;其他模型(第三方供应商的模型、路由器把供应商名当模型名上报)没有官方峰谷定价,卡片把这两项都隐藏,而不是显示一个与实际账单不符的数字。
112
+ - 比本插件版本更新的官方模型同样不在表里,卡片会隐藏价格,直到价格表更新。
109
113
  - 放假日期维护在 `lib/pricing.js` 的 `HOLIDAY_RANGES`。国务院办公厅通常在前一年 11 月发布次年安排,届时更新;未更新前,节假日会按普通工作日处理,白天显示高峰价。
110
114
 
111
115
  ### 简单的工作原理
package/lib/client.js CHANGED
@@ -16,6 +16,8 @@
16
16
  // (历史上圆点的 title 里塞过这些,已删除)。
17
17
  // · 唯一的交互是「点击卡片刷新」;没有可切换的提示态。
18
18
  // · 只有余额类错误(未配置 Key / 余额接口或网络失败)才置空卡片说明原因。
19
+ // · 档单价与峰谷指示灯只对 DeepSeek 官方模型展示(内置价格表命中);其他模型
20
+ // (第三方供应商、路由组合名)不适用官方峰谷定价,整组隐藏,卡片只留余额。
19
21
  // 样式仅使用 `--dsw-*` 主题变量(含兜底值),跟随明暗主题。
20
22
  window.__ModuleLoader__.load({
21
23
  id: "@dougen/dsh-deepseek-usage",
@@ -360,6 +362,14 @@ window.__ModuleLoader__.load({
360
362
  const balance = data && data.balance ? data.balance : null;
361
363
  const tier = data && data.tier ? data.tier : null;
362
364
  const symbol = balance && balance.currency === "USD" ? "$" : "¥";
365
+ // 档单价与峰谷指示灯只对 DeepSeek 官方模型有意义:官方价格表与峰谷时段不适用于
366
+ // 第三方供应商的模型(gpt-5-pro 这类),也不适用于路由器把供应商名当模型传上来的
367
+ // 情况(如 codebuddy、codebuddy,deepseek-v4.1-flash)——那种情况下内置表算出的
368
+ // 数字与用户实际账单无关,显示出来就是错的。
369
+ // 宿主用 tier.known 表达这件事(见 lib/pricing.js 的 isOfficialModel / lookup):
370
+ // known=false 就是"这个模型的价格插件不知道",档单价与峰谷都无从展示。
371
+ // 拿不到 tier(宿主刚重启、请求失败)时按已知处理,避免卡片在收敛过程中闪成半张脸。
372
+ const priced = tier ? tier.known !== false : true;
363
373
  // 卡片只显示"用户要的数字":余额、当前档单价、状态圆点、距下次切换的倒计时。
364
374
  // 插件的内部信息(取价路径、模型改名)一律不进 UI,
365
375
  // 唯一的交互是点击卡片刷新。只有"余额类错误"(未配置 Key / 接口或网络失败)才
@@ -397,7 +407,9 @@ window.__ModuleLoader__.load({
397
407
  // 折叠态(图标栏):内容宽 36px(侧边栏 56px − 折叠态左右各 10px 内边距),
398
408
  // 只容得下峰谷指示灯,没有外框也没有底色(直接坐在侧边栏背景上)。
399
409
  // 指示灯仍是"点击刷新"的落点。
410
+ // 非官方模型时这个栏里没有任何有意义的内容(余额在折叠态放不下),整块不渲染。
400
411
  if (!wide) {
412
+ if (!priced) return null;
401
413
  return h("div", {
402
414
  style: {
403
415
  boxSizing: "border-box",
@@ -491,7 +503,8 @@ window.__ModuleLoader__.load({
491
503
  // 负 margin 只挪动整组,不改变金额行高度(卡片高度由内边距决定)。
492
504
  // 实测:marginTop -4 与 marginRight -3 时,圆点距卡片顶、右各 8px
493
505
  // (右侧不能按"内边距 10 − 8"去推,内边距本就含在行宽里)。
494
- h("span", { style: { display: "flex", alignItems: "center", gap: 6, minWidth: 0, marginLeft: "auto", flex: "0 1 auto", alignSelf: "flex-start", marginTop: -4, marginRight: -3 } },
506
+ // 非官方模型时整组不渲染:没有官方峰谷时段,倒计时与指示灯都无从谈起。
507
+ priced && h("span", { style: { display: "flex", alignItems: "center", gap: 6, minWidth: 0, marginLeft: "auto", flex: "0 1 auto", alignSelf: "flex-start", marginTop: -4, marginRight: -3 } },
495
508
  // 倒计时:距下次峰谷切换的剩余时间(`2d 15h` / `5h 47m` / `23m` / `switching`)。
496
509
  // 纯英文单位、无前缀,中英界面一致。
497
510
  // 字号/字重刻意与右下角单价数字对齐(继承卡片正文 12px、fontWeight 600),
@@ -508,12 +521,13 @@ window.__ModuleLoader__.load({
508
521
  }, countdown),
509
522
  // 峰谷指示灯:只有颜色(橙=高峰 / 绿=空闲),没有 title、没有其他文字。
510
523
  h("span", { style: dot }))),
511
- // 底部行:只剩当前档单价,恒靠右下角。
524
+ // 底部行:只剩当前档单价,恒靠右下角。非官方模型时整行不渲染
525
+ // (内置价格表算出的数字与它们的实际账单无关)。
512
526
  // 这组 bottom:2 + 卡片下内边距 10 是用户看过多组对比后选定的观感(价格略微下移、
513
527
  // 下方不再空一大块)。注意绝对定位的行不参与卡片高度计算,改内边距时两者要一起看。
514
528
  // 用 flex-end 而不是 space-between:容器只有一个子元素时 space-between 会把它
515
529
  // 推到最左侧(0.6.0 的回归点)。
516
- h("span", {
530
+ priced && h("span", {
517
531
  style: { position: "absolute", left: 9, right: 9, bottom: 2, display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 6 },
518
532
  },
519
533
  h("span", { style: { display: "inline-flex", alignItems: "center", gap: 5, flex: "none" } },
package/lib/pricing.js CHANGED
@@ -12,6 +12,10 @@
12
12
  * reasoner),命中即按现名计价;
13
13
  * · 两条路径都会在 unitAt() 的 via 字段里标出来源,供排查,避免静默算错。
14
14
  *
15
+ * 只对 DeepSeek 官方模型计价(isOfficialModel):第三方供应商的模型与路由器把供应商名
16
+ * 当模型名上报的情况(codebuddy、codebuddy,deepseek-v4.1-flash)一律 known=false,
17
+ * 界面据此隐藏档单价与峰谷指示灯——官方价格表与峰谷时段对它们不成立。
18
+ *
15
19
  * 峰谷(官方口径):高峰时段为北京时间周一至周五(**不含中国法定节假日**)
16
20
  * 9:00–12:00、14:00–18:00,其余(含整个周末、法定节假日全天、以及调休上班的
17
21
  * 周末)为空闲时段;缓存写暂不计费(cacheWrite = 0)。
@@ -182,6 +186,22 @@ function familyOf(id) {
182
186
  return m ? m[1] : null;
183
187
  }
184
188
 
189
+ /**
190
+ * 是否是 DeepSeek 官方模型(官方价格表与峰谷时段只对它们成立)。
191
+ *
192
+ * 只看模型名:官方模型的 id 一律以 `deepseek-` / `deepseek.` 开头(deepseek-flash、
193
+ * deepseek-v4-pro、deepseek-chat、deepseek-reasoner 及其旧名)。第三方供应商的模型
194
+ * (gpt-5-pro 这类)与路由器把供应商名当模型名传进来的情况(codebuddy、
195
+ * codebuddy,deepseek-v4.1-flash)都不匹配——它们的计费口径与官方峰谷价无关,
196
+ * 按内置表算出来的数字会与用户实际账单不一致。
197
+ *
198
+ * 不用"家族匹配"(familyOf)判断:familyOf('gpt-5-pro') 也命中 pro,会把第三方
199
+ * 模型误判成官方 V4 Pro。家族匹配只用于官方模型改名后的取价兜底。
200
+ */
201
+ export function isOfficialModel(model) {
202
+ return typeof model === 'string' && /^deepseek[-.]/i.test(model.trim());
203
+ }
204
+
185
205
  const has = (obj, key) => !!obj && Object.prototype.hasOwnProperty.call(obj, key);
186
206
 
187
207
  /** 别名(旧名 → 现名)。 */
@@ -207,9 +227,14 @@ function lookupId(id) {
207
227
 
208
228
  /**
209
229
  * 解析模型的计价条目:精确 → 别名 → 同家族唯一匹配 → chat 档兜底。
230
+ * 非官方模型(见 isOfficialModel)不查表:即便名字里带 chat/pro 等家族词,也直接按
231
+ * known=false 返回,由调用方隐藏档单价与峰谷指示灯。
210
232
  * @returns {{ price: object, id: string, via: 'exact'|'alias'|'family'|'fallback', known: boolean }}
211
233
  */
212
234
  function lookup(model) {
235
+ if (!isOfficialModel(model)) {
236
+ return { price: PRICE_TABLE['deepseek-chat'], id: 'deepseek-chat', via: 'fallback', known: false };
237
+ }
213
238
  const found = lookupId(model);
214
239
  if (found) return { price: PRICE_TABLE[found.id], id: found.id, via: found.via, known: true };
215
240
  return { price: PRICE_TABLE['deepseek-chat'], id: 'deepseek-chat', via: 'fallback', known: false };
@@ -222,7 +247,8 @@ export function isKnownModel(model) {
222
247
 
223
248
  /**
224
249
  * 某模型在某一时刻的单位价格(元/百万 tokens)。
225
- * 未知模型回退 chat 档;known=false 供调用方提示,避免静默算错。
250
+ * 非官方模型(见 isOfficialModel)与不在表里的官方模型都会走 chat 档兜底,但
251
+ * known=false 会把这件事告诉调用方:那份兜底价与它们的实际账单无关,界面应隐藏。
226
252
  * via 说明取价路径(exact / alias / family / fallback),供排查与回归测试。
227
253
  */
228
254
  export function unitAt(model, ms) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dougen/dsh-deepseek-usage",
3
- "version": "0.11.1",
4
- "description": "A DeepSeek Harness sidebar plugin: your balance (official API), the active model's unit prices and a peak/off-peak indicator, in a Chinese/English UI. / DeepSeek Harness 侧边栏插件:余额(官方 API)、当前模型档单价与峰谷时段指示灯,界面支持中英文。",
3
+ "version": "0.12.0",
4
+ "description": "A DeepSeek Harness sidebar plugin: your balance (official API), and for official DeepSeek models the active model's unit prices and a peak/off-peak indicator, in a Chinese/English UI. / DeepSeek Harness 侧边栏插件:余额(官方 API);当前模型为 DeepSeek 官方模型时,另显示档单价与峰谷时段指示灯。界面支持中英文。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "repository": {