dsh-balance-widget 0.6.2 → 0.6.3

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.en.md CHANGED
@@ -144,7 +144,7 @@ If you mainly use DeepSeek-V4-Pro, point the pricing model at it for a more accu
144
144
 
145
145
  ## Pricing
146
146
 
147
- Built-in DeepSeek official peak/off-peak pricing (CNY per 1M tokens), effective 2026-09-10. Peak windows are Beijing time **Mon–Fri** 09:00–12:00 and 14:00–18:00 (weekends are off-peak all day); prices are double the off-peak rates:
147
+ Built-in DeepSeek official peak/off-peak pricing (CNY per 1M tokens), effective 2026-09-10. Peak windows are Beijing time **Mon–Fri (China's statutory holidays excluded)** 09:00–12:00 and 14:00–18:00; **everything else is off-peak**, weekends (including 调休 make-up workdays) and statutory holidays all day included. Peak prices are double the off-peak rates:
148
148
 
149
149
  | Model | Window | Cache hit (input) | Cache miss (input) | Output |
150
150
  | --- | --- | --- | --- | --- |
@@ -192,6 +192,13 @@ This section is for the DSH Store / plugin audit: dependencies, runtime permissi
192
192
 
193
193
  ## Changelog
194
194
 
195
+ ### v0.6.3 — China's statutory holidays are now priced off-peak all day
196
+ - 🐛 **Fixed**: the peak/off-peak check excluded weekends but **not China's statutory holidays**. The official rule is "Beijing time **Mon–Fri (China's statutory holidays excluded)** 09:00–12:00 and 14:00–18:00 are peak; everything else — weekends and statutory holidays all day — is off-peak", so a statutory holiday falling on a weekday was **priced at 2×**. Measured against the built-in 2026 arrangement: Spring Festival 2/18, Dragon Boat 6/19, Mid-Autumn 9/25 and National Day 10/1–10/7 were all mispriced as peak, doubling their cost
197
+ - 📅 **The 2026 statutory holiday table is built in** ([国办发明电〔2025〕7号](https://www.gov.cn/zhengce/zhengceku/202511/content_7047091.htm); **33 days** across New Year, Spring Festival, Qingming, Labour Day, Dragon Boat, Mid-Autumn and National Day — **19 of them on weekdays**, exactly the ones that used to be priced at 2×), matched on the Beijing calendar day. Make-up workdays that fall on a Saturday or Sunday were already off-peak (the official rule lists weekends outright); they are now pinned by tests too
198
+ - 🧪 **Differential verification**: 14 fixture sessions (each with its own fake `$HOME`, driven through the real route, real zstd frames and real pricing) assert ¥1.00 all day on holidays, ¥2.00 inside a normal weekday peak window, and the first working day after a holiday plus the lunch/evening boundaries — **14/14 pass**. Running the same cases against the pre-fix code fails all six holiday cases (¥2.00)
199
+ - ⚠️ **Maintenance note**: the table needs an annual refresh (the State Council publishes the next arrangement, usually in the previous November); years it does not cover fall back to the old weekend-only rule
200
+ - 📄 **Docs**: the pricing section and the peak/off-peak tooltips (both languages) now state "statutory holidays excluded / make-up workdays included" precisely
201
+
195
202
  ### v0.6.2 — the balance now prefers the official account service (same source as the settings page, no API key needed)
196
203
  - ✨ **The balance is read from the host account service `deepseekAccount` (provided by `@deepseek-ai/dsh-deepseek-account-platform`)** whenever DSH >= 0.2.0 ships it **and a DeepSeek account is signed in**. That service is the official "Settings → Account & balance" page's own source, so the card and the settings page show the same number. Amounts follow the official rule — **positive values are truncated to cents** (`55.6787307800000000` → `55.67`, matching the page) — with the purchased wallet from `value[]`, the granted wallet from `bonusWallets[]`, their sum as the total, and one entry per currency
197
204
  - 🚪 **Every fallback is unchanged**: when signed out, when the host has no such service (DSH 0.1.x), or when the account read fails (expired token and friends), the balance comes from the original `GET /user/balance` + `DEEPSEEK_API_KEY`, exactly as in 0.6.1; a failed account read logs one warning saying why
package/README.md CHANGED
@@ -141,7 +141,7 @@ DSH 的插件配置统一放在这个文件里:
141
141
 
142
142
  ## 定价说明
143
143
 
144
- 内置 DeepSeek 官方 2026-09-10 峰谷定价(元 / 百万 tokens),高峰时段为北京时间**周一至周五** 09:00–12:00、14:00–18:00(周末全天为空闲时段),价格为空闲时段两倍:
144
+ 内置 DeepSeek 官方 2026-09-10 峰谷定价(元 / 百万 tokens),高峰时段为北京时间**周一至周五(不含中国法定节假日)** 09:00–12:00、14:00–18:00;**其余时段全部为空闲时段**,包括周末(含调休上班的周六/周日)与中国法定节假日全天,价格为空闲时段两倍。
145
145
 
146
146
  | 模型 | 时段 | 缓存命中(输入) | 缓存未命中(输入) | 输出 |
147
147
  | --- | --- | --- | --- | --- |
@@ -189,6 +189,13 @@ DSH 的插件配置统一放在这个文件里:
189
189
 
190
190
  ## 版本历史
191
191
 
192
+ ### v0.6.3 — 中国法定节假日全天按空闲时段计价
193
+ - 🐛 **修复**:峰/谷判断只排除了周末,**没有排除中国法定节假日**。官方规则是「北京时间**周一至周五(不含中国法定节假日)** 09:00–12:00、14:00–18:00 为高峰时段;其余时段,包括周末及中国法定节假日全天均为空闲时段」——所以落在工作日的法定假日,此前会被**按 2× 计价**。以内置 2026 年安排实测:春节 2/18、端午 6/19、中秋 9/25、国庆 10/1–10/7 全部被误判为峰时,成本翻倍
194
+ - 📅 **内置 2026 年法定节假日表**([国办发明电〔2025〕7号](https://www.gov.cn/zhengce/zhengceku/202511/content_7047091.htm),含元旦/春节/清明/劳动/端午/中秋/国庆共 **33 天**,其中 **19 天落在工作日**——正是此前会被 2× 计价的那部分),按北京时间日历日匹配;调休上班的周六/周日**本来就已按周末计**(官方明确按空闲时段),本次一并写入测试用例防回归
195
+ - 🧪 **差分验证**:新建 14 个夹具会话(每个自带假 `$HOME`,走真实路由 + 真实 zstd 帧 + 真实定价),断言节假日全天 ¥1.00、普通工作日峰窗 ¥2.00、节后首个工作日与午休/晚间边界均正确 —— **14/14 通过**;用修复前的代码跑同一组用例,6 个节假日用例全部失败(¥2.00)
196
+ - ⚠️ **维护提示**:节假日表需每年更新(国务院办公厅通常在上一年 11 月发布下一年安排),未覆盖的年份会退回"仅排除周末"的旧行为
197
+ - 📄 **文档**:定价说明与峰谷 tooltip(中英)补上"不含法定节假日 / 含调休上班日"的准确表述
198
+
192
199
  ### v0.6.2 — 余额优先读官方账号服务(与设置页同源,不再需要 API Key)
193
200
  - ✨ **余额优先取自宿主账号服务 `deepseekAccount`**:当 DSH ≥ 0.2.0 **且已登录 DeepSeek 账号**时,余额改读这个服务——它就是官方「设置 → 账号与余额」页的数据来源,所以卡片与设置页显示同一个数字。金额按官方规则处理:**正金额截断至分**(`55.6787307800000000` → `55.67`,与设置页一致),充值余额 = 官方 `value[]`、赠金余额 = `bonusWallets[]`,总额为两者之和,多币种各自成组
194
201
  - 🚪 **降级路径完全不变**:未登录、宿主无该服务(DSH 0.1.x)、或账号读取失败(token 过期等)时,一律回退到原来的 `GET /user/balance` + `DEEPSEEK_API_KEY`,行为与 0.6.1 相同;账号读取失败会记一条 warn 说明原因
package/lib/client.js CHANGED
@@ -564,8 +564,8 @@ window.__ModuleLoader__.load({
564
564
  "todayCostShort": "今日·全部",
565
565
  "peak.active": "峰时",
566
566
  "peak.offpeak": "谷时",
567
- "peak.tooltip.active": "当前为峰时(周一至周五 09:00-12:00、14:00-18:00,价格翻倍):输入 ¥{input}/M · 输出 ¥{output}/M",
568
- "peak.tooltip.offpeak": "当前为谷时(其余时段含周末全天,半价):输入 ¥{input}/M · 输出 ¥{output}/M",
567
+ "peak.tooltip.active": "当前为峰时(周一至周五 09:00-12:00、14:00-18:00,不含法定节假日,价格翻倍):输入 ¥{input}/M · 输出 ¥{output}/M",
568
+ "peak.tooltip.offpeak": "当前为谷时(其余时段:周末含调休上班日、法定节假日全天,半价):输入 ¥{input}/M · 输出 ¥{output}/M",
569
569
  "sessionNote": "基于最近活跃会话:",
570
570
  "hint": "价格为估算值,实际以官方账单为准。",
571
571
  "topUp": "去充值",
@@ -595,8 +595,8 @@ window.__ModuleLoader__.load({
595
595
  "todayCostShort": "Today · all",
596
596
  "peak.active": "Peak",
597
597
  "peak.offpeak": "Off-peak",
598
- "peak.tooltip.active": "Peak hours now (Mon-Fri 09:00-12:00, 14:00-18:00, 2× price): input ¥{input}/M · output ¥{output}/M",
599
- "peak.tooltip.offpeak": "Off-peak hours now (all other times incl. weekends, half price): input ¥{input}/M · output ¥{output}/M",
598
+ "peak.tooltip.active": "Peak hours now (Mon-Fri 09:00-12:00, 14:00-18:00, statutory holidays excluded, 2× price): input ¥{input}/M · output ¥{output}/M",
599
+ "peak.tooltip.offpeak": "Off-peak hours now (everything else: weekends incl. make-up workdays, statutory holidays all day, half price): input ¥{input}/M · output ¥{output}/M",
600
600
  "sessionNote": "Based on most recent session:",
601
601
  "hint": "Prices are estimates; actual billing from the provider is authoritative.",
602
602
  "topUp": "Top up",
package/lib/index.js CHANGED
@@ -358,17 +358,56 @@ const PRICING_ALIASES = {
358
358
  "deepseek-official": "deepseek-v4-flash"
359
359
  };
360
360
 
361
+ /**
362
+ * Statutory holiday days (Beijing calendar dates) of the 2026 arrangement,
363
+ * per 国办发明电〔2025〕7号. DeepSeek bills Beijing time 周一至周五(**不含中国
364
+ * 法定节假日**)09:00-12:00 / 14:00-18:00 as peak; everything else — weekends
365
+ * (including 调休 workdays) and statutory holidays all day — is off-peak, so a
366
+ * weekday holiday must never be priced as peak. Weekend days are listed too:
367
+ * harmless here, and it keeps the table a verbatim copy of the notice.
368
+ * Refresh once a year, when the State Council publishes the next arrangement
369
+ * (usually the previous November).
370
+ */
371
+ const CN_HOLIDAYS = new Set([
372
+ // 元旦:1月1日(周四)至3日(周六)
373
+ "2026-01-01", "2026-01-02", "2026-01-03",
374
+ // 春节:2月15日(周日)至23日(周一)
375
+ "2026-02-15", "2026-02-16", "2026-02-17", "2026-02-18", "2026-02-19",
376
+ "2026-02-20", "2026-02-21", "2026-02-22", "2026-02-23",
377
+ // 清明节:4月4日(周六)至6日(周一)
378
+ "2026-04-04", "2026-04-05", "2026-04-06",
379
+ // 劳动节:5月1日(周五)至5日(周二)
380
+ "2026-05-01", "2026-05-02", "2026-05-03", "2026-05-04", "2026-05-05",
381
+ // 端午节:6月19日(周五)至21日(周日)
382
+ "2026-06-19", "2026-06-20", "2026-06-21",
383
+ // 中秋节:9月25日(周五)至27日(周日)
384
+ "2026-09-25", "2026-09-26", "2026-09-27",
385
+ // 国庆节:10月1日(周四)至7日(周三)
386
+ "2026-10-01", "2026-10-02", "2026-10-03", "2026-10-04", "2026-10-05",
387
+ "2026-10-06", "2026-10-07"
388
+ ]);
389
+
390
+ /** The Beijing (UTC+8) calendar day of an instant, as "YYYY-MM-DD". */
391
+ function beijingDay(date) {
392
+ const beijing = new Date(date.getTime() + 8 * 60 * 60 * 1000);
393
+ const month = String(beijing.getUTCMonth() + 1).padStart(2, "0");
394
+ const day = String(beijing.getUTCDate()).padStart(2, "0");
395
+ return `${beijing.getUTCFullYear()}-${month}-${day}`;
396
+ }
397
+
361
398
  /**
362
399
  * Whether `date` falls inside a Beijing-time (UTC+8) peak window.
363
400
  * DeepSeek's peak pricing applies to Beijing time 09:00-12:00 and 14:00-18:00
364
- * on weekdays only (Mon-Fri); the whole weekend is off-peak. The window is
365
- * computed in UTC+8 explicitly instead of the machine's local time, which also
366
- * supplies the Beijing weekday.
401
+ * on weekdays only, and explicitly excludes China's statutory holidays; the
402
+ * whole weekend counts as off-peak even when a 调休 turns it into a workday.
403
+ * The window is computed in UTC+8 explicitly instead of the machine's local
404
+ * time, which also supplies the Beijing weekday and calendar day.
367
405
  */
368
406
  function isPeak(date) {
369
407
  const beijing = new Date(date.getTime() + 8 * 60 * 60 * 1000);
370
408
  const day = beijing.getUTCDay(); // 0 = Sunday, 6 = Saturday
371
409
  if (day === 0 || day === 6) return false;
410
+ if (CN_HOLIDAYS.has(beijingDay(date))) return false;
372
411
  const hour = beijing.getUTCHours();
373
412
  return (hour >= 9 && hour < 12) || (hour >= 14 && hour < 18);
374
413
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-balance-widget",
3
3
  "description": "Balance & cost widget for the DeepSeek Harness GUI (web and desktop app): a sidebar footer card shows the DeepSeek account balance and today's costs; clicking opens a popover with a five-tier cost breakdown (last prompt with session name / today-this-session / today-this-workspace / today-all-workspaces), peak/off-peak status tag, term explanations, and a one-click top-up link. Zero external dependencies — works on Node 24.",
4
- "version": "0.6.2",
4
+ "version": "0.6.3",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "files": [