dsh-cost-meter 1.5.18 → 1.5.20

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
@@ -4,9 +4,9 @@
4
4
 
5
5
  **Session cost tracking plugin for the DeepSeek Harness web GUI (bilingual UI)**
6
6
 
7
- Per-conversation cost · daily totals · OpenCode Go subscription quota display · budget with usage percentage · official account balance · custom provider balance · balance progress bar · history · peak/off-peak pricing hours display (peak hours UTC 01:00–04:00, 06:00–10:00) · one-click price sync from the official docs · Codex-style token usage heat grid · multi-vendor model pricing (built-in 90+ model price catalog with auto-matching) · mainstream Coding Plan quota queries & display (Anthropic / Z.ai / MiniMax / Kimi / OpenRouter / SiliconFlow)
7
+ Per-conversation cost · daily totals · OpenCode Go subscription quota display · budget with usage percentage · official account balance · custom provider balance · balance progress bar · history · peak/off-peak pricing hours display (peak hours UTC 01:00–04:00, 06:00–10:00) · pre-switch popup & system-notification alerts for peak/off-peak changes (position / lead time / alert type configurable) · one-click price sync from the official docs · Codex-style token usage heat grid · multi-vendor model pricing (built-in 90+ model price catalog with auto-matching) · mainstream Coding Plan quota queries & display (Anthropic / Z.ai / MiniMax / Kimi / OpenRouter / SiliconFlow / SCNet)
8
8
 
9
- [![version](https://img.shields.io/badge/version-1.5.18-4176E6)](https://github.com/Han-1413141/dsh-cost-meter)
9
+ [![version](https://img.shields.io/badge/version-1.5.20-4176E6)](https://github.com/Han-1413141/dsh-cost-meter)
10
10
  [![npm](https://img.shields.io/npm/v/dsh-cost-meter?label=npm)](https://www.npmjs.com/package/dsh-cost-meter)
11
11
  [![license](https://img.shields.io/badge/license-MIT-green)](LICENSE)
12
12
  [![dsh](https://img.shields.io/badge/DeepSeek%20Harness-dsh--plugin-4176E6)](https://github.com/deepseek-ai/deepseek-harness)
@@ -40,7 +40,7 @@ English | [中文](README.md)
40
40
  | Budget settings | Settings page, top | Limit, period (today / month / cumulative / custom date range), used % |
41
41
  | Price table | Settings page | Per-model off-peak / peak prices (input/output shorthand supported; cache prices derived automatically); fully editable |
42
42
  | Peak/off-peak hours display | Settings / budget / today | Shows UTC peak hours 01:00–04:00 and 06:00–10:00 with the current tier; expanded view shows a peak/off-peak period strip (current period + countdown), collapsed (rail) view shows a vertical peak/off-peak progress bar; independently toggleable |
43
- | Peak/off-peak switch popup alert | Global overlay | A full-width bracketed popup appears when the next tier switch is within the configured lead time (default 2 minutes, 1–30), with an alert-colored badge distinguishing entering peak vs off-peak; position selectable (**bottom-right / screen center**), alert type selectable (entering peak / entering off-peak / both), one alert per switch point; optionally **sends a browser (system) notification** (so you still get alerted when the page is backgrounded; requires granting notification permission); configured in the peak pricing panel in Settings |
43
+ | Peak/off-peak switch popup alert | Global overlay | A full-width bracketed popup appears when the next tier switch is within the configured lead time (default 2 minutes, 1–30), with an alert-colored badge distinguishing entering peak vs off-peak; position selectable (**bottom-right / screen center**), alert type selectable (entering peak / entering off-peak / both), one alert per switch point; optionally **sends a browser (system) notification** (so you still get alerted when the page is backgrounded; requires granting notification permission); configured in the peak pricing panel in Settings, with a **one-click popup preview** (rendered by the real component — copy, position and notifications exactly as they will fire) |
44
44
  | Official price sync | Settings page | Fetches and parses the official pricing page, applies with one click |
45
45
  | UI language | Settings → Display settings | Simplified Chinese / English / Follow browser (auto); switches instantly and auto-saves |
46
46
  | AI price sync | [prompt](docs/AI-PRICE-SYNC-PROMPT.en.md) | DeepSeek official sync; other providers use the verified official price catalog and manual configuration |
@@ -193,22 +193,22 @@ Real captures from an actual DSH sidebar of the period strip and collapsed verti
193
193
  dsh plugin --profile web add dsh-cost-meter
194
194
  ```
195
195
 
196
- **PowerShell one-click script** (copy the whole line, paste, press Enter; pnpm is provisioned automatically, git is auto-detected — no clone needed; the install chain is **pinned to the release tag `v1.5.18`** — review the script before running):
196
+ **PowerShell one-click script** (copy the whole line, paste, press Enter; pnpm is provisioned automatically, git is auto-detected — no clone needed; the install chain is **pinned to the release tag `v1.5.20`** — review the script before running):
197
197
 
198
198
  ```powershell
199
- irm https://raw.githubusercontent.com/Han-1413141/dsh-cost-meter/v1.5.18/install.ps1 | iex
199
+ irm https://raw.githubusercontent.com/Han-1413141/dsh-cost-meter/v1.5.20/install.ps1 | iex
200
200
  ```
201
201
 
202
202
  **Or a plain command line** (the machine must already have pnpm and git; also pinned to the tag):
203
203
 
204
204
  ```sh
205
- dsh plugin --profile web add github:Han-1413141/dsh-cost-meter#v1.5.18
205
+ dsh plugin --profile web add github:Han-1413141/dsh-cost-meter#v1.5.20
206
206
  ```
207
207
 
208
208
  Without git, use the GitHub tag archive:
209
209
 
210
210
  ```sh
211
- dsh plugin --profile web add https://github.com/Han-1413141/dsh-cost-meter/archive/refs/tags/v1.5.18.tar.gz
211
+ dsh plugin --profile web add https://github.com/Han-1413141/dsh-cost-meter/archive/refs/tags/v1.5.20.tar.gz
212
212
  ```
213
213
 
214
214
  After installing, **restart** `dsh web` (plugin rows, the Typert manifest and the client bundle are all scanned at startup):
package/README.md CHANGED
@@ -4,9 +4,9 @@
4
4
 
5
5
  **DeepSeek Harness 会话费用统计插件(界面中英双语)**
6
6
 
7
- 本会话费用 · 当日费用 · OpenCode Go 订阅额度显示 · 预算与已用百分比 · 官方账户余额 · 自定义 Provider 余额查询(可配任意 HTTP 端点) · 余额三段进度条 · 历史记录 · 峰谷计价时段显示(UTC 01:00–04:00、06:00–10:00 为峰时段) · 官方价格一键同步 · 类 Codex Token 用量热图 · 多厂商多模型价格计费(内置 90+ 模型价格目录与自动匹配) · 主流 Coding Plan 额度查询与显示(Anthropic / Z.ai / MiniMax / Kimi / OpenRouter / SiliconFlow 六家)
7
+ 本会话费用 · 当日费用 · OpenCode Go 订阅额度显示 · 预算与已用百分比 · 官方账户余额 · 自定义 Provider 余额查询(可配任意 HTTP 端点) · 余额三段进度条 · 历史记录 · 峰谷计价时段显示(UTC 01:00–04:00、06:00–10:00 为峰时段) · 峰/谷切换前弹窗与系统通知提醒(位置/提前量/提醒类型可配) · 官方价格一键同步 · 类 Codex Token 用量热图 · 多厂商多模型价格计费(内置 90+ 模型价格目录与自动匹配) · 主流 Coding Plan 额度查询与显示(Anthropic / Z.ai / MiniMax / Kimi / OpenRouter / SiliconFlow / SCNet 七家)
8
8
 
9
- [![version](https://img.shields.io/badge/version-1.5.18-4176E6)](https://github.com/Han-1413141/dsh-cost-meter)
9
+ [![version](https://img.shields.io/badge/version-1.5.20-4176E6)](https://github.com/Han-1413141/dsh-cost-meter)
10
10
  [![npm](https://img.shields.io/npm/v/dsh-cost-meter?label=npm)](https://www.npmjs.com/package/dsh-cost-meter)
11
11
  [![license](https://img.shields.io/badge/license-MIT-green)](LICENSE)
12
12
  [![dsh](https://img.shields.io/badge/DeepSeek%20Harness-dsh--plugin-4176E6)](https://github.com/deepseek-ai/deepseek-harness)
@@ -41,7 +41,7 @@
41
41
  | 预算设置 | 设置页顶部 | 额度、周期(今日/本月/累计/自定义日期区间)、已用% |
42
42
  | 价格表 | 设置页 | 每模型 谷时/峰时 两档价格(支持 input/output 简写,缓存价自动补齐),增删改自由 |
43
43
  | 峰谷计价时段显示 | 设置页 / 预算 / 今日费用 | 显示 UTC 峰时段 01:00–04:00、06:00–10:00 与当前档位;展开态显示峰时/平价时段条(当前时段 + 倒计时),收起(rail)态显示竖向峰谷进度条,可单独开关 |
44
- | 峰/谷切换弹窗提醒 | 全局浮层 | 距进入峰/谷时段不足设定提前量(默认 2 分钟,1-30 可配)时全屏色条徽标弹窗(提醒色区分进入峰/谷);弹窗位置可选**右下角 / 屏幕中心**,提醒类型可选(进入峰 / 进入谷 / 峰和谷),同一切换点只提醒一次;可选**同步发送浏览器(系统)通知**(页面最小化也能收到,需授权通知权限),设置页峰谷计价面板内配置 |
44
+ | 峰/谷切换弹窗提醒 | 全局浮层 | 距进入峰/谷时段不足设定提前量(默认 2 分钟,1-30 可配)时全屏色条徽标弹窗(提醒色区分进入峰/谷);弹窗位置可选**右下角 / 屏幕中心**,提醒类型可选(进入峰 / 进入谷 / 峰和谷),同一切换点只提醒一次;可选**同步发送浏览器(系统)通知**(页面最小化也能收到,需授权通知权限);设置页峰谷计价面板内配置,并可**一键预览弹窗效果**(真实组件渲染,文案/位置/通知与实际触发完全一致) |
45
45
  | 官方价格同步 | 设置页 | 抓取解析官方定价页,一键应用 |
46
46
  | 界面语言 | 设置页 → 显示设置 | 简体中文 / English / 跟随浏览器(自动);切换即时生效并自动保存 |
47
47
  | AI 价格同步 | [提示词](docs/AI-PRICE-SYNC-PROMPT.md) | DeepSeek 官方同步;其他 provider 使用已核对的官方价格目录与手动配置 |
@@ -195,22 +195,22 @@
195
195
  dsh plugin --profile web add dsh-cost-meter
196
196
  ```
197
197
 
198
- **PowerShell 一键脚本**(复制整行粘贴回车;自动补齐 pnpm、自动探测 git,无需克隆仓库;安装链**固定到发布 tag `v1.5.18`**,建议先下载审阅再运行):
198
+ **PowerShell 一键脚本**(复制整行粘贴回车;自动补齐 pnpm、自动探测 git,无需克隆仓库;安装链**固定到发布 tag `v1.5.20`**,建议先下载审阅再运行):
199
199
 
200
200
  ```powershell
201
- irm https://raw.githubusercontent.com/Han-1413141/dsh-cost-meter/v1.5.18/install.ps1 | iex
201
+ irm https://raw.githubusercontent.com/Han-1413141/dsh-cost-meter/v1.5.20/install.ps1 | iex
202
202
  ```
203
203
 
204
204
  **或直接命令行**(机器上需已有 pnpm 与 git;同样固定到 tag):
205
205
 
206
206
  ```sh
207
- dsh plugin --profile web add github:Han-1413141/dsh-cost-meter#v1.5.18
207
+ dsh plugin --profile web add github:Han-1413141/dsh-cost-meter#v1.5.20
208
208
  ```
209
209
 
210
210
  没有 git 时可用 GitHub tag 打包直链:
211
211
 
212
212
  ```sh
213
- dsh plugin --profile web add https://github.com/Han-1413141/dsh-cost-meter/archive/refs/tags/v1.5.18.tar.gz
213
+ dsh plugin --profile web add https://github.com/Han-1413141/dsh-cost-meter/archive/refs/tags/v1.5.20.tar.gz
214
214
  ```
215
215
 
216
216
  安装后**重启** `dsh web`(插件行、Typert 清单与客户端 bundle 均在启动时扫描):
package/lib/client.js CHANGED
@@ -122,6 +122,7 @@ window.__ModuleLoader__.load({
122
122
  '.cm-peak-alert-title{font-size:14px;font-weight:600;color:var(--dsw-alias-label-primary)}',
123
123
  '.cm-peak-alert-body{color:var(--dsw-alias-label-secondary);line-height:1.55}',
124
124
  '.cm-peak-alert-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:2px}',
125
+ '.cm-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}',
125
126
  '@keyframes cm-peak-alert-in{from{opacity:0;transform:translateY(10px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}',
126
127
  '@keyframes cm-peak-alert-in-center{from{opacity:0;transform:translate(-50%,calc(-50% + 10px))}to{opacity:1;transform:translate(-50%,-50%)}}',
127
128
  '.cm-budget-head{display:flex;align-items:center;justify-content:space-between;gap:8px}',
@@ -455,6 +456,10 @@ window.__ModuleLoader__.load({
455
456
  peakAlertPositionCenter: '屏幕中心',
456
457
  peakAlertWebNotifyLabel: '同步发送系统通知',
457
458
  peakAlertWebNotifyHint: '开关后请在浏览器地址栏允许通知权限,才能在页面最小化/切走时收到提醒。',
459
+ peakAlertPreviewLabel: '预览弹窗',
460
+ peakAlertPreviewPeak: '预览 进入峰',
461
+ peakAlertPreviewOffPeak: '预览 进入谷',
462
+ peakAlertPreviewTag: '(预览)',
458
463
  peakPanelTitle: '峰谷计价与提示',
459
464
  peakNoticeHiddenHint: '提示已隐藏:需启用峰谷计价并开启「峰时高价时段显著提示」。',
460
465
  groupGeneral: '常规',
@@ -775,6 +780,10 @@ window.__ModuleLoader__.load({
775
780
  peakAlertPositionCenter: 'Screen center',
776
781
  peakAlertWebNotifyLabel: 'Also send a system notification',
777
782
  peakAlertWebNotifyHint: 'When enabled, allow notification permission in the browser address bar so you get alerted even when the page is minimized or backgrounded.',
783
+ peakAlertPreviewLabel: 'Preview the popup',
784
+ peakAlertPreviewPeak: 'Preview entering peak',
785
+ peakAlertPreviewOffPeak: 'Preview entering off-peak',
786
+ peakAlertPreviewTag: ' (preview)',
778
787
  peakPanelTitle: 'Peak/off-peak pricing & notice',
779
788
  peakNoticeHiddenHint: 'Notice hidden: enable peak/off-peak pricing and the “prominent notice” toggle.',
780
789
  groupGeneral: 'General',
@@ -2011,22 +2020,52 @@ window.__ModuleLoader__.load({
2011
2020
  : t('countdownMinute', { m: minutes })
2012
2021
  }
2013
2022
 
2023
+ // 预览通道事件名:设置页按钮/控制台经 window.cmPeakAlertPreview(kind) 触发真实组件。
2024
+ const PEAK_ALERT_PREVIEW_EVENT = 'cm-peak-alert-preview'
2025
+
2014
2026
  /**
2015
2027
  * 峰/谷切换前弹窗提醒:距下次相位切换不足配置提前量(默认 2 分钟)时弹浮层,
2016
2028
  * 位置可选屏幕右下角 / 屏幕中心;提醒类型按配置过滤(进入峰/进入谷/峰和谷);
2017
2029
  * 同一切换点只弹一次(手动关闭即记点),切换完成后浮层自然消失。
2018
2030
  * 若开启 Web 通知且有授权,还会在同一切换点向系统发送一次浏览器通知。
2031
+ * 预览:window.cmPeakAlertPreview('peak'|'offpeak') 用真实组件/文案/位置/通知
2032
+ * 渲染一次弹窗(峰谷计价启用时常驻监听,提醒开关关闭也可预览)。
2019
2033
  */
2020
2034
  function PeakAlert(props) {
2021
2035
  const costStore = props.useCost ? props.useCost(s => s) : undefined
2022
2036
  const config = costStore?.state?.config
2023
2037
  const [now, setNow] = useState(Date.now())
2024
2038
  const [dismissedAt, setDismissedAt] = useState(null)
2039
+ const [preview, setPreview] = useState(null)
2025
2040
  const notifiedAtRef = useRef(null)
2026
2041
  useEffect(() => {
2027
2042
  const timer = window.setInterval(() => setNow(Date.now()), 10000)
2028
2043
  return () => window.clearInterval(timer)
2029
2044
  }, [])
2045
+ // 预览通道:监听自定义事件;同时在 window 上暴露便捷 API 供设置页与控制台调用。
2046
+ useEffect(() => {
2047
+ const onPreview = event => {
2048
+ const kind = event.detail?.kind === 'offpeak' ? 'offpeak' : 'peak'
2049
+ setPreview(kind)
2050
+ // 预览系统通知:遵循 Web 通知开关与授权,标题加预览标记。
2051
+ const cfg = costStore?.state?.config
2052
+ if (cfg?.peakAlertWebNotify === true && window.Notification && Notification.permission === 'granted') {
2053
+ const pt = makeT(resolveLocale(cfg.locale))
2054
+ try {
2055
+ new Notification(pt(kind === 'peak' ? 'peakAlertTitlePeak' : 'peakAlertTitleOffPeak') + pt('peakAlertPreviewTag'),
2056
+ { body: pt('peakAlertBody', { time: pt('countdownMinute', { m: 2 }), phase: pt(kind === 'peak' ? 'peakAlertPhasePeak' : 'peakAlertPhaseOffPeak') }) })
2057
+ } catch (_) { /* 通知被系统拒绝时静默 */ }
2058
+ }
2059
+ }
2060
+ window.addEventListener(PEAK_ALERT_PREVIEW_EVENT, onPreview)
2061
+ window.cmPeakAlertPreview = kind => {
2062
+ window.dispatchEvent(new CustomEvent(PEAK_ALERT_PREVIEW_EVENT, { detail: { kind: kind === 'offpeak' ? 'offpeak' : 'peak' } }))
2063
+ }
2064
+ return () => {
2065
+ window.removeEventListener(PEAK_ALERT_PREVIEW_EVENT, onPreview)
2066
+ delete window.cmPeakAlertPreview
2067
+ }
2068
+ }, []) // eslint-disable-line react-hooks/exhaustive-deps
2030
2069
  useEffect(() => {
2031
2070
  // Web 通知:每次 tick 自包含重算切换点,同一切换点只发一次。
2032
2071
  if (!config || config.peakAlertEnabled !== true || config.peakEnabled !== true) return
@@ -2048,21 +2087,35 @@ window.__ModuleLoader__.load({
2048
2087
  { body: t('peakAlertBody', { time: countdownText(wv, now, t), phase: t(intoPeak ? 'peakAlertPhasePeak' : 'peakAlertPhaseOffPeak') }) })
2049
2088
  } catch (_) { /* 通知被系统拒绝时静默 */ }
2050
2089
  }, [now]) // eslint-disable-line react-hooks/exhaustive-deps
2051
- if (!config || config.peakAlertEnabled !== true || config.peakEnabled !== true) return null
2052
- const effectiveAtMs = Date.parse(config.peakEffectiveAt || '')
2053
- if (Number.isFinite(effectiveAtMs) && now < effectiveAtMs) return null
2054
- const view = peakPhaseAt(now, Array.isArray(config.peakWindows) ? config.peakWindows : [])
2055
- if (view === null) return null
2056
- const target = config.peakAlertTarget === 'peak' || config.peakAlertTarget === 'offpeak' ? config.peakAlertTarget : 'both'
2057
- if (target !== 'both' && target !== (view.nextIntoPeak ? 'peak' : 'offpeak')) return null
2058
- const aheadMinutes = Number(config.peakAlertAhead)
2059
- const aheadMs = (Number.isFinite(aheadMinutes) && aheadMinutes >= 1 ? aheadMinutes : 2) * 60000
2060
- if (now < view.nextAtMs - aheadMs || now >= view.nextAtMs) return null
2061
- if (dismissedAt === view.nextAtMs) return null
2090
+ if (!config || config.peakEnabled !== true) return null
2091
+ // 真实弹窗判定:提醒开关开启 + 已生效 + 相位/类型/提前量窗口内 + 未手动关闭。
2092
+ let real = null
2093
+ if (config.peakAlertEnabled === true) {
2094
+ const effectiveAtMs = Date.parse(config.peakEffectiveAt || '')
2095
+ if (!(Number.isFinite(effectiveAtMs) && now < effectiveAtMs)) {
2096
+ const view = peakPhaseAt(now, Array.isArray(config.peakWindows) ? config.peakWindows : [])
2097
+ if (view !== null) {
2098
+ const target = config.peakAlertTarget === 'peak' || config.peakAlertTarget === 'offpeak' ? config.peakAlertTarget : 'both'
2099
+ const aheadMinutes = Number(config.peakAlertAhead)
2100
+ const aheadMs = (Number.isFinite(aheadMinutes) && aheadMinutes >= 1 ? aheadMinutes : 2) * 60000
2101
+ if ((target === 'both' || target === (view.nextIntoPeak ? 'peak' : 'offpeak'))
2102
+ && now >= view.nextAtMs - aheadMs && now < view.nextAtMs && dismissedAt !== view.nextAtMs) real = view
2103
+ }
2104
+ }
2105
+ }
2106
+ // 渲染:真实窗口激活用真实切换点;否则若有预览请求,用虚拟切换点(2 分钟后)。
2107
+ let view = null, intoPeak = false, dismiss = null
2108
+ if (real !== null) {
2109
+ view = real
2110
+ intoPeak = real.nextIntoPeak === true
2111
+ dismiss = () => setDismissedAt(real.nextAtMs)
2112
+ } else if (preview !== null) {
2113
+ view = { nextAtMs: now + 2 * 60000, nextIntoPeak: preview === 'peak' }
2114
+ intoPeak = preview === 'peak'
2115
+ dismiss = () => setPreview(null)
2116
+ } else return null
2062
2117
  const t = makeT(resolveLocale(config.locale))
2063
- const intoPeak = view.nextIntoPeak === true
2064
2118
  const position = config.peakAlertPosition === 'center' ? 'cm-peak-alert-center' : 'cm-peak-alert-corner'
2065
- const actionBtn = (className, label, fn) => el('button', { className, onClick: fn }, label)
2066
2119
  return el('div', { className: 'cm-peak-alert ' + position + ' ' + (intoPeak ? 'cm-peak-alert-peak' : 'cm-peak-alert-offpeak'), role: 'alert' },
2067
2120
  el('div', { className: 'cm-peak-alert-badge' }, t(intoPeak ? 'peakAlertBadgePeak' : 'peakAlertBadgeOffPeak')),
2068
2121
  el('div', { className: 'cm-peak-alert-title' }, t(intoPeak ? 'peakAlertTitlePeak' : 'peakAlertTitleOffPeak')),
@@ -2071,7 +2124,7 @@ window.__ModuleLoader__.load({
2071
2124
  phase: t(intoPeak ? 'peakAlertPhasePeak' : 'peakAlertPhaseOffPeak'),
2072
2125
  })),
2073
2126
  el('div', { className: 'cm-peak-alert-actions' },
2074
- actionBtn('cm-btn', t('peakAlertBtn'), () => setDismissedAt(view.nextAtMs))))
2127
+ el('button', { className: 'cm-btn', onClick: dismiss }, t('peakAlertBtn'))))
2075
2128
  }
2076
2129
 
2077
2130
  /** 展开态简洁样式:单行紧凑时段条——细轨道(左橙右蓝,非当前段淡化)+ 标记线 + 右侧倒计时文本。 */
@@ -2893,6 +2946,11 @@ window.__ModuleLoader__.load({
2893
2946
  }),
2894
2947
  el('span', null, t('peakAlertWebNotifyLabel'))),
2895
2948
  el('p', { className: 'cm-hint' }, t('peakAlertWebNotifyHint')))),
2949
+ el('div', { className: 'cm-field' },
2950
+ el('label', null, t('peakAlertPreviewLabel')),
2951
+ el('div', { className: 'cm-row' },
2952
+ el('button', { className: 'cm-btn', onClick: () => window.cmPeakAlertPreview?.('peak') }, t('peakAlertPreviewPeak')),
2953
+ el('button', { className: 'cm-btn', onClick: () => window.cmPeakAlertPreview?.('offpeak') }, t('peakAlertPreviewOffPeak')))),
2896
2954
  el('div', { className: 'cm-peak-preview' },
2897
2955
  draft?.peakEnabled !== false && draft?.peakNotice !== false
2898
2956
  ? peakNoticeEl(state, previewConfig, t)
@@ -4696,7 +4754,8 @@ window.__ModuleLoader__.load({
4696
4754
  registerCorner(cornerEnabled)
4697
4755
  lastCorner = cornerEnabled
4698
4756
  }
4699
- const peakAlertOn = state?.config?.peakAlertEnabled !== false && state?.config?.peakEnabled === true
4757
+ // 峰谷计价启用即常驻挂载(提醒开关关闭时也保留组件,供设置页预览弹窗)。
4758
+ const peakAlertOn = state?.config?.peakEnabled === true
4700
4759
  if (peakAlertOn !== lastPeakAlert) {
4701
4760
  registerPeakAlert(peakAlertOn)
4702
4761
  lastPeakAlert = peakAlertOn
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-cost-meter",
3
- "version": "1.5.18",
4
- "description": "DeepSeek Harness 会话费用统计插件:本会话成本、当日费用、历史记录与官方价格同步,支持多厂商多模型价格计费(内置 90+ 模型价格目录与自动匹配)、主流 Coding Plan 订阅额度查询与显示(7 家,含 SCNet Token Plan 本地 Credits 计量)、自定义 Provider 余额查询(可配任意 HTTP 端点)与余额进度条,界面中英双语。Session cost tracking plugin for DeepSeek Harness: per-conversation cost, daily totals, history and official price sync, with multi-vendor model pricing (built-in 90+ model catalog with auto-matching), Coding Plan quota queries & display for 7 vendors (incl. local credits metering for the SCNet Token Plan), custom provider balance lookup (configurable HTTP endpoint) and balance progress bar, in a bilingual (Chinese/English) UI.",
3
+ "version": "1.5.20",
4
+ "description": "DeepSeek Harness 会话费用统计插件:本会话成本、当日费用、历史记录与官方价格同步,支持多厂商多模型价格计费(内置 90+ 模型价格目录与自动匹配)、主流 Coding Plan 订阅额度查询与显示(7 家,含 SCNet Token Plan 本地 Credits 计量)、自定义 Provider 余额查询(可配任意 HTTP 端点)与余额进度条、峰谷计价时段显示与切换前弹窗/系统通知提醒(位置/提前量/类型可配),界面中英双语。Session cost tracking plugin for DeepSeek Harness: per-conversation cost, daily totals, history and official price sync, with multi-vendor model pricing (built-in 90+ model catalog with auto-matching), Coding Plan quota queries & display for 7 vendors (incl. local credits metering for the SCNet Token Plan), custom provider balance lookup (configurable HTTP endpoint) and balance progress bar, plus peak/off-peak pricing display with pre-switch popup & system-notification alerts (position / lead time / type configurable), in a bilingual (Chinese/English) UI.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "exports": {
@@ -27,7 +27,7 @@
27
27
  "dshhub": {
28
28
  "schemaVersion": 1,
29
29
  "displayName": "dsh-cost-meter",
30
- "summary": "DeepSeek Harness 会话费用统计:本会话费用、预算图框、官方余额、自定义 Provider 余额查询、Coding Plan 额度查询、历史记录,支持峰谷计价与官方价格一键同步。",
30
+ "summary": "DeepSeek Harness 会话费用统计:本会话费用、预算图框、官方余额、自定义 Provider 余额查询、Coding Plan 额度查询、历史记录,支持峰谷计价(切换前弹窗与系统通知提醒)与官方价格一键同步。",
31
31
  "categories": ["费用", "Web UI", "观测"],
32
32
  "surfaces": ["host", "web"],
33
33
  "capabilities": {