deepseek-harness-wallet 0.3.4 → 0.3.5
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 +5 -0
- package/README.md +3 -3
- package/index.js +1 -1
- package/lib/client.js +1 -1
- package/lib/plans.js +30 -19
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## 0.3.5 - 2026-08-27
|
|
6
|
+
|
|
7
|
+
- 修复 BigModel / Z.ai 中国区 Coding Plan 接口将 `TOKENS_LIMIT` 改名为 `CREDIT_LIMIT` 后被误判为“套餐接口返回格式已变化”的问题;兼容新旧字段,支持只有新额度字段的响应,并在接口提供时显示已用/总量、剩余量和重置时间。 / Fixed BigModel / Z.ai China Coding Plan responses being misclassified as “the plan response format changed” after `TOKENS_LIMIT` was renamed to `CREDIT_LIMIT`; both names are supported, credit-only responses are accepted, and available used/total, remaining, and reset values are shown when provided.
|
|
8
|
+
- 增加新旧字段共存时优先保留信息更完整的额度数据,并补充接口归一化与回归测试;当前 126/126 测试通过。 / Prefer the richer quota record when old and new names coexist, with normalization and regression coverage; 126/126 tests pass.
|
|
9
|
+
|
|
5
10
|
## 0.3.4 - 2026-08-25
|
|
6
11
|
|
|
7
12
|
- 修复 DSH Desktop 重启后部分插件设置因 WebView origin/localStorage 命名空间变化而丢失的问题:显示内容、输入框标签、仅显示余额、标签比例、提醒、峰谷卡和永久删除偏好现在会即时写入浏览器并同步备份到本地 `wallet.json`;宿主已有值优先恢复,宿主缺失的旧设置才从浏览器迁移,避免旧标签页在重启后反向覆盖新选择。 / Fixed wallet preferences disappearing after a DSH Desktop restart when the WebView origin/localStorage namespace changes: display, composer-label, primary-value, scale, reminder, peak-card, and permanent-delete preferences now write locally and mirror into `wallet.json`; existing host values restore authoritatively, while browser values migrate only for host-missing keys so stale tabs cannot undo newer choices after restart (Fixes #31).
|
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
> A local-first companion that keeps account status, per-conversation usage, completion reminders, official recharge, flexible layout, and host-gated session controls beside the DSH composer.
|
|
16
16
|
|
|
17
|
-
> **Version:** v0.3.
|
|
17
|
+
> **Version:** v0.3.5 is the current stable release on GitHub and npm.
|
|
18
18
|
|
|
19
19
|
> If DeepSeek Harness Control Center helps you, please consider leaving a ⭐ Star. Thank you!
|
|
20
20
|
|
|
@@ -73,13 +73,13 @@ Details: [compatibility](#browser-desktop-and-os-compatibility) · [data and tru
|
|
|
73
73
|
|
|
74
74
|
## Install
|
|
75
75
|
|
|
76
|
-
From npm (stable v0.3.
|
|
76
|
+
From npm (stable v0.3.5):
|
|
77
77
|
|
|
78
78
|
```sh
|
|
79
79
|
dsh plugin --profile web add deepseek-harness-wallet
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
or from GitHub `main` (current v0.3.
|
|
82
|
+
or from GitHub `main` (current v0.3.5 source):
|
|
83
83
|
|
|
84
84
|
```sh
|
|
85
85
|
dsh plugin --profile web add github:feibi-mochi/deepseek-harness-control-center
|
package/index.js
CHANGED
|
@@ -33,7 +33,7 @@ const OFFICIAL_PROVIDER = 'deepseek-official'
|
|
|
33
33
|
// DeepSeek's official paid-API bucket by the wrapper-provider alias control.
|
|
34
34
|
const PLAN_PROVIDER_IDS = new Set(PLAN_ADAPTERS.map((adapter) => adapter.provider))
|
|
35
35
|
const RECHARGE_URL = 'https://platform.deepseek.com/top_up'
|
|
36
|
-
const PLUGIN_VERSION = '0.3.
|
|
36
|
+
const PLUGIN_VERSION = '0.3.5'
|
|
37
37
|
const PRICING_SOURCE_URL = 'https://api-docs.deepseek.com/zh-cn/quick_start/pricing/'
|
|
38
38
|
const PRICING_SYNC_INTERVAL_MS = 6 * 60 * 60_000
|
|
39
39
|
const PRICING_SYNC_TIMEOUT_MS = 8_000
|
package/lib/client.js
CHANGED
|
@@ -23,7 +23,7 @@ window.__ModuleLoader__.load({
|
|
|
23
23
|
|
|
24
24
|
var POLL_MS = 15000
|
|
25
25
|
// Keep in lockstep with package.json; a test enforces the sync.
|
|
26
|
-
var WALLET_VERSION = '0.3.
|
|
26
|
+
var WALLET_VERSION = '0.3.5'
|
|
27
27
|
var CONFIRM_KEY = 'dsh-wallet-recharge-confirmed'
|
|
28
28
|
var CHIP_LAYOUT_KEY = 'dshw-chip-layout-v4'
|
|
29
29
|
var PANEL_POS_KEY = 'dshw-panel-pos-v1'
|
package/lib/plans.js
CHANGED
|
@@ -8,8 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
export const PLAN_CACHE_VERSION = 2
|
|
10
10
|
|
|
11
|
+
const TOKEN_LIMIT = Object.freeze({ id: 'tokens-5h', kind: 'tokens', window: '5h', amounts: false, reset: false })
|
|
12
|
+
const CREDIT_LIMIT = Object.freeze({ id: 'tokens-5h', kind: 'tokens', window: '5h', amounts: true, reset: true })
|
|
13
|
+
|
|
11
14
|
const ZAI_LIMITS = Object.freeze({
|
|
12
|
-
|
|
15
|
+
// BigModel renamed this response type to CREDIT_LIMIT without changing
|
|
16
|
+
// the 5-hour model-credit semantics. Keep both names for old snapshots and
|
|
17
|
+
// new China-region responses.
|
|
18
|
+
TOKENS_LIMIT: TOKEN_LIMIT,
|
|
19
|
+
CREDIT_LIMIT,
|
|
13
20
|
TIME_LIMIT: Object.freeze({ id: 'tools-month', kind: 'tools', window: 'month' }),
|
|
14
21
|
})
|
|
15
22
|
|
|
@@ -81,9 +88,9 @@ function normalizedLimit(adapter, value, atMs) {
|
|
|
81
88
|
if (value === null || typeof value !== 'object' || Array.isArray(value)) return null
|
|
82
89
|
const descriptor = adapter.limitTypes[value.type]
|
|
83
90
|
if (descriptor === undefined) return null
|
|
84
|
-
const used = descriptor.kind === 'tools' ? finiteNonNegative(value.currentValue) : null
|
|
85
|
-
const total = descriptor.kind === 'tools' ? finiteNonNegative(value.usage) : null
|
|
86
|
-
const remaining = descriptor.kind === 'tools' ? finiteNonNegative(value.remaining) : null
|
|
91
|
+
const used = descriptor.amounts ? finiteNonNegative(value.currentValue) : descriptor.kind === 'tools' ? finiteNonNegative(value.currentValue) : null
|
|
92
|
+
const total = descriptor.amounts ? finiteNonNegative(value.usage) : descriptor.kind === 'tools' ? finiteNonNegative(value.usage) : null
|
|
93
|
+
const remaining = descriptor.amounts ? finiteNonNegative(value.remaining) : descriptor.kind === 'tools' ? finiteNonNegative(value.remaining) : null
|
|
87
94
|
const percentages = percentagePair(value.percentage, used, total)
|
|
88
95
|
return {
|
|
89
96
|
id: descriptor.id,
|
|
@@ -93,18 +100,26 @@ function normalizedLimit(adapter, value, atMs) {
|
|
|
93
100
|
used,
|
|
94
101
|
total,
|
|
95
102
|
remaining,
|
|
96
|
-
resetAt: descriptor.kind === 'tools' ? resetTimestamp(value.nextResetTime, atMs) : null,
|
|
103
|
+
resetAt: descriptor.reset || descriptor.kind === 'tools' ? resetTimestamp(value.nextResetTime, atMs) : null,
|
|
97
104
|
}
|
|
98
105
|
}
|
|
99
106
|
|
|
107
|
+
function preferRicherLimit(next, current) {
|
|
108
|
+
if (current === undefined) return true
|
|
109
|
+
if (current.used === null && next.used !== null) return true
|
|
110
|
+
if (current.total === null && next.total !== null) return true
|
|
111
|
+
if (current.remaining === null && next.remaining !== null) return true
|
|
112
|
+
return current.resetAt === null && next.resetAt !== null
|
|
113
|
+
}
|
|
114
|
+
|
|
100
115
|
function normalizeCachedLimit(value, atMs) {
|
|
101
116
|
if (value === null || typeof value !== 'object' || Array.isArray(value)) return null
|
|
102
117
|
if (!['tokens-5h', 'tools-month'].includes(value.id)) return null
|
|
103
118
|
const kind = value.id === 'tokens-5h' ? 'tokens' : 'tools'
|
|
104
119
|
const window = value.id === 'tokens-5h' ? '5h' : 'month'
|
|
105
|
-
const used =
|
|
106
|
-
const total =
|
|
107
|
-
const remaining =
|
|
120
|
+
const used = finiteNonNegative(value.used)
|
|
121
|
+
const total = finiteNonNegative(value.total)
|
|
122
|
+
const remaining = finiteNonNegative(value.remaining)
|
|
108
123
|
const legacyUsedPercentage = value.usedPercentage ?? value.percentage
|
|
109
124
|
const percentages = percentagePair(legacyUsedPercentage, used, total)
|
|
110
125
|
return {
|
|
@@ -115,7 +130,7 @@ function normalizeCachedLimit(value, atMs) {
|
|
|
115
130
|
used,
|
|
116
131
|
total,
|
|
117
132
|
remaining,
|
|
118
|
-
resetAt:
|
|
133
|
+
resetAt: resetTimestamp(value.resetAt, atMs),
|
|
119
134
|
}
|
|
120
135
|
}
|
|
121
136
|
|
|
@@ -127,14 +142,12 @@ export function normalizePlanPayload(adapter, payload, atMs = Date.now()) {
|
|
|
127
142
|
}
|
|
128
143
|
const data = payload.data !== null && typeof payload.data === 'object' && !Array.isArray(payload.data) ? payload.data : null
|
|
129
144
|
if (data === null || !Array.isArray(data.limits)) throw new Error('invalid-plan-response')
|
|
130
|
-
const
|
|
131
|
-
const seen = new Set()
|
|
145
|
+
const limitsById = new Map()
|
|
132
146
|
for (const item of data.limits) {
|
|
133
147
|
const limit = normalizedLimit(adapter, item, atMs)
|
|
134
|
-
if (limit
|
|
135
|
-
seen.add(limit.id)
|
|
136
|
-
limits.push(limit)
|
|
148
|
+
if (limit !== null && preferRicherLimit(limit, limitsById.get(limit.id))) limitsById.set(limit.id, limit)
|
|
137
149
|
}
|
|
150
|
+
const limits = [...limitsById.values()]
|
|
138
151
|
limits.sort((left, right) => left.id === 'tokens-5h' ? -1 : right.id === 'tokens-5h' ? 1 : left.id.localeCompare(right.id))
|
|
139
152
|
if (limits.length === 0) throw new Error('invalid-plan-response')
|
|
140
153
|
return {
|
|
@@ -156,14 +169,12 @@ export function normalizePlanSnapshotCache(value, atMs = Date.now()) {
|
|
|
156
169
|
? Math.trunc(raw.fetchedAt)
|
|
157
170
|
: null
|
|
158
171
|
if (fetchedAt === null || !Array.isArray(raw.limits)) continue
|
|
159
|
-
const
|
|
160
|
-
const seen = new Set()
|
|
172
|
+
const limitsById = new Map()
|
|
161
173
|
for (const item of raw.limits) {
|
|
162
174
|
const limit = normalizeCachedLimit(item, atMs)
|
|
163
|
-
if (limit
|
|
164
|
-
seen.add(limit.id)
|
|
165
|
-
limits.push(limit)
|
|
175
|
+
if (limit !== null && preferRicherLimit(limit, limitsById.get(limit.id))) limitsById.set(limit.id, limit)
|
|
166
176
|
}
|
|
177
|
+
const limits = [...limitsById.values()]
|
|
167
178
|
if (limits.length === 0) continue
|
|
168
179
|
limits.sort((left, right) => left.id === 'tokens-5h' ? -1 : right.id === 'tokens-5h' ? 1 : left.id.localeCompare(right.id))
|
|
169
180
|
out[adapter.id] = {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deepseek-harness-wallet",
|
|
3
3
|
"description": "Local-first DeepSeek Harness control center for balance monitoring, usage accounting, a 365-day local token ledger, Z.ai Coding Plan quota monitoring, official pricing sync, peak/off-peak status, encrypted multi-account switching, health checks, completion reminders, recharge, and host-gated session controls.",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.5",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"exports": {
|