dsh-whale-widget 0.2.8 → 0.2.9
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 +2 -2
- package/lib/index.js +36 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ DeepSeek Harness(DSH)Web 界面右下角的常驻余额挂件:小鲸鱼气
|
|
|
10
10
|
- 💰 **余额**:60 秒自动刷新 + 点击鲸鱼手动刷新;余额变化时数字**滚动动画**;瞬时网络抖动自动沿用最近余额不报错
|
|
11
11
|
- 📊 **今日已用**:两种模式任选(见下),显示今日消耗金额
|
|
12
12
|
- **小鲸鱼记账(推荐,免令牌)**:不需要任何会话令牌,鲸鱼娘每次观测余额后用余额差值自动记账(`.dshw-usage.json`,跨天自动归零归档)
|
|
13
|
-
-
|
|
13
|
+
- **实时·令牌**:填入平台会话令牌后直接调用平台用量接口,按**峰谷定价**(工作日高峰 9:00–12:00 与 14:00–18:00,其余空闲;2026-08-23 起周末全天按谷价)实时换算今日已用
|
|
14
14
|
- 💬 **每轮对话消耗统计**:监听本机会话事件,每轮对话结束后弹出本轮消耗金额(精确 usage,非估算)
|
|
15
15
|
- 菜单可开关「每轮对话后自动显示消耗金额」;「自动关闭时间」可自定义秒数(填 0 表示不自动关闭)
|
|
16
16
|
- 消耗金额泡泡显示期间,余额变动不弹普通泡泡
|
|
@@ -146,7 +146,7 @@ Remove-Item "$web\DSniang02.png" -ErrorAction SilentlyContinue
|
|
|
146
146
|
|
|
147
147
|
**① 小鲸鱼记账(推荐,默认)—— 完全不需要额外配置**
|
|
148
148
|
|
|
149
|
-
鲸鱼娘自己用**余额差值**记账:每次观测到余额下降就把差值累加到当天用量,跨天自动归零归档(保留 30
|
|
149
|
+
鲸鱼娘自己用**余额差值**记账:每次观测到余额下降就把差值累加到当天用量,跨天自动归零归档(保留 30 天);观测币种发生变化时只重置基准、不记差值(防止多币种账户切换污染账本)。只要配好了 `DEEPSEEK_API_KEY` 就能用,**开箱即用**。
|
|
150
150
|
|
|
151
151
|
- 账本文件:`$DSH_HOME/.dshw-usage.json`(自动生成)
|
|
152
152
|
- 优点:零配置、免令牌
|
package/lib/index.js
CHANGED
|
@@ -63,7 +63,8 @@ const RUA_GIF_CANDIDATES = [
|
|
|
63
63
|
'D:/TestBox/deepseek/rua.gif',
|
|
64
64
|
]
|
|
65
65
|
// DeepSeek CNY prices per million tokens: [空闲时段价, 高峰时段价].
|
|
66
|
-
//
|
|
66
|
+
// 高峰时段:工作日 9:00–12:00 和 14:00–18:00(北京时间);2026-08-23 起周末全天谷价。
|
|
67
|
+
// Adjust here if DeepSeek changes pricing.
|
|
67
68
|
const PEAK_HOURS = [
|
|
68
69
|
[9, 12],
|
|
69
70
|
[14, 18],
|
|
@@ -88,9 +89,18 @@ function priceFor(model) {
|
|
|
88
89
|
return PRICING._default
|
|
89
90
|
}
|
|
90
91
|
// bucket time is an epoch second; derive the Beijing local hour to pick peak vs off-peak price.
|
|
92
|
+
// 2026-08-23 起(北京时间)周末(周六/周日)全天按谷价;生效时刻之前的历史
|
|
93
|
+
// 分桶仍按旧规则计价,所以周末判定带生效分界。
|
|
94
|
+
const WEEKEND_VALLEY_FROM_SEC = Math.floor(Date.UTC(2026, 7, 22, 16, 0, 0) / 1000) // = 北京时间 2026-08-23 00:00
|
|
91
95
|
function isPeakTime(timeSec) {
|
|
92
96
|
if (!isFinite(Number(timeSec))) return false
|
|
93
|
-
const
|
|
97
|
+
const n = Number(timeSec)
|
|
98
|
+
const bj = new Date(n * 1000 + 8 * 3600 * 1000)
|
|
99
|
+
if (n >= WEEKEND_VALLEY_FROM_SEC) {
|
|
100
|
+
const dow = bj.getUTCDay() // 0=周日 6=周六(bj 按 UTC 读即为北京日历日)
|
|
101
|
+
if (dow === 0 || dow === 6) return false
|
|
102
|
+
}
|
|
103
|
+
const hour = bj.getUTCHours()
|
|
94
104
|
for (const [start, end] of PEAK_HOURS) {
|
|
95
105
|
if (hour >= start && hour < end) return true
|
|
96
106
|
}
|
|
@@ -611,6 +621,10 @@ function showCostBubble(amount) {
|
|
|
611
621
|
if (costBubbleTimer) { clearTimeout(costBubbleTimer); costBubbleTimer = null }
|
|
612
622
|
if (bubbleTimer) { clearTimeout(bubbleTimer); bubbleTimer = null }
|
|
613
623
|
if (gifFadeTimer) { clearTimeout(gifFadeTimer); gifFadeTimer = null }
|
|
624
|
+
// 取消进行中的余额数字滚动与延迟计时器,避免竞态覆盖成本金额
|
|
625
|
+
if (animId) { cancelAnimationFrame(animId); animId = null }
|
|
626
|
+
if (animDelayTimer) { clearTimeout(animDelayTimer); animDelayTimer = null }
|
|
627
|
+
if (settleTimer) { clearTimeout(settleTimer); settleTimer = null }
|
|
614
628
|
costBubbleActive = true
|
|
615
629
|
bubbleRandomActive = false
|
|
616
630
|
bubbleShown = true
|
|
@@ -672,6 +686,11 @@ function animateAmount(from, to, currency, duration) {
|
|
|
672
686
|
}
|
|
673
687
|
var startTime = null
|
|
674
688
|
function step(ts) {
|
|
689
|
+
// 帧级保护:成本泡泡出现后立即停止滚动,避免后续帧把余额写进金额行
|
|
690
|
+
if (costBubbleActive) {
|
|
691
|
+
animId = null
|
|
692
|
+
return
|
|
693
|
+
}
|
|
675
694
|
if (startTime === null) startTime = ts
|
|
676
695
|
var t = Math.min(1, (ts - startTime) / duration)
|
|
677
696
|
var eased = 1 - Math.pow(1 - t, 3)
|
|
@@ -1640,10 +1659,16 @@ function apply(ctx) {
|
|
|
1640
1659
|
}
|
|
1641
1660
|
return false
|
|
1642
1661
|
}
|
|
1643
|
-
//
|
|
1644
|
-
|
|
1662
|
+
// 记账模式:每次观测到余额后,用余额正差值累计当天用量(跨天自动归零并归档)。
|
|
1663
|
+
// 币种感知:观测币种与上次不同时只重置基准、不记差值——数值跳变来自币种
|
|
1664
|
+
// 切换而非真实消费([0] 选币时代 CNY/USD 随机切换曾记出巨额假账,见 #13)。
|
|
1665
|
+
function recordLedgerUsage(currentBalance, currency) {
|
|
1645
1666
|
const t = todayKey()
|
|
1646
1667
|
let led = readUsageLedger()
|
|
1668
|
+
const cur = String(currency || '')
|
|
1669
|
+
const currencyChanged =
|
|
1670
|
+
typeof led.lastCurrency === 'string' && led.lastCurrency !== '' &&
|
|
1671
|
+
cur !== '' && led.lastCurrency !== cur
|
|
1647
1672
|
if (led.date !== t) {
|
|
1648
1673
|
if (led.date && typeof led.todayUsage === 'number') {
|
|
1649
1674
|
led.history = led.history || {}
|
|
@@ -1651,13 +1676,19 @@ function apply(ctx) {
|
|
|
1651
1676
|
}
|
|
1652
1677
|
led.date = t
|
|
1653
1678
|
led.lastBalance = currentBalance
|
|
1679
|
+
led.lastCurrency = cur
|
|
1654
1680
|
led.todayUsage = 0
|
|
1681
|
+
} else if (currencyChanged) {
|
|
1682
|
+
// 币种切换:只换基准,不把差值记成消费
|
|
1683
|
+
led.lastBalance = currentBalance
|
|
1684
|
+
led.lastCurrency = cur
|
|
1655
1685
|
} else {
|
|
1656
1686
|
const prev = typeof led.lastBalance === 'number' ? led.lastBalance : currentBalance
|
|
1657
1687
|
if (typeof prev === 'number' && typeof currentBalance === 'number' && currentBalance < prev) {
|
|
1658
1688
|
led.todayUsage = (typeof led.todayUsage === 'number' ? led.todayUsage : 0) + (prev - currentBalance)
|
|
1659
1689
|
}
|
|
1660
1690
|
led.lastBalance = currentBalance
|
|
1691
|
+
led.lastCurrency = cur
|
|
1661
1692
|
}
|
|
1662
1693
|
const keys = Object.keys(led.history || {}).sort()
|
|
1663
1694
|
while (keys.length > 30) {
|
|
@@ -1674,7 +1705,7 @@ function apply(ctx) {
|
|
|
1674
1705
|
const payload = await fetchBalance()
|
|
1675
1706
|
if (!payload.ok) return payload
|
|
1676
1707
|
// 无论哪种模式,都先把余额观测记入账本(自动累积「鲸鱼记账」数据)
|
|
1677
|
-
const led = recordLedgerUsage(Number(payload.totalBalance))
|
|
1708
|
+
const led = recordLedgerUsage(Number(payload.totalBalance), payload.currency)
|
|
1678
1709
|
const cfg = readSizeConfig() || {}
|
|
1679
1710
|
const mode = normalizeUsageMode(cfg.usageMode)
|
|
1680
1711
|
const full = { ...payload }
|