@dougen/dsh-deepseek-usage 0.8.0 → 0.9.1
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 +11 -0
- package/lib/client.js +50 -38
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ DeepSeek **余额侧边栏插件**(DeepSeek Harness Web UI):在 DSH **网
|
|
|
14
14
|
- **Auto price sync**: prices are re-fetched from the official DeepSeek pricing page on first use each day and when you click the card; the result is merged back into the price table (official entries overwrite same-named ones, your own entries are kept). The page is parsed **structurally (HTML table cells)**, not by matching surrounding text, so official layout/rewording changes no longer break it; a plain-text strategy remains as a fallback
|
|
15
15
|
- **Rename-proof model mapping**: when DeepSeek renames a model (e.g. `deepseek-v4-flash` → `deepseek-flash`) the old id is charged at the current model's price instead of silently showing an outdated price. (The card stays quiet about this — see *FAQ* below.)
|
|
16
16
|
- **Peak indicator & countdown**: top-right dot — orange during peak hours (Mon–Fri 9:00–12:00, 14:00–18:00 Beijing Time), green otherwise. Beside the dot a countdown shows the time left until the next peak/off-peak switch, in English units (`2d 15h`, `5h 47m`, `23m`).
|
|
17
|
+
- **Collapsed sidebar**: with the sidebar collapsed to the icon rail, this plugin shows the peak/off-peak dot alone (clicking it still refreshes); the full card returns when the sidebar expands.
|
|
17
18
|
- **Auto refresh**: every 5 minutes; click the card to refresh instantly.
|
|
18
19
|
- **i18n**: UI copy follows the DSH locale (Chinese / English)
|
|
19
20
|
- Follows the app light/dark theme
|
|
@@ -24,6 +25,7 @@ DeepSeek **余额侧边栏插件**(DeepSeek Harness Web UI):在 DSH **网
|
|
|
24
25
|
- **单价自动同步**:每日首次使用或点击卡片时,自动从官方价格页拉取最新档单价,并把结果**合并回写**到价格表(官方条目覆盖同名项,你自己加的条目保留)。页面解析采用**结构化表格解析**(直接读 HTML 表格单元格),不再依赖"正文里某段文字长什么样",官方改版/改文案不会失效;另保留纯文本兜底策略
|
|
25
26
|
- **抗改名映射**:官方给模型改名(如 `deepseek-v4-flash` → `deepseek-flash`)时,旧名按现名价格计费,不会静默显示旧价(卡片不为此弹提示,见下方 FAQ)
|
|
26
27
|
- **峰谷指示灯与倒计时**:卡片右上角圆点,高峰(周一至周五 9:00–12:00、14:00–18:00 北京时间)橙色,空闲绿色;圆点旁显示距下次峰谷切换的倒计时,统一英文单位(`2d 15h`、`5h 47m`、`23m`)
|
|
28
|
+
- **侧边栏折叠**:折叠成图标栏时只显示峰谷指示灯(点击它同样可刷新),卡片在侧边栏展开时回来
|
|
27
29
|
- **自动刷新**:每 5 分钟一次;点击卡片任意位置立即刷新
|
|
28
30
|
- **多语言**:界面文案跟随 DSH 语言(中文 / English)
|
|
29
31
|
- 跟随应用明暗主题
|
|
@@ -154,6 +156,15 @@ node lib/pricing-remote.js --check --html page.html --json
|
|
|
154
156
|
> `node --test --test-isolation=none "test/*.test.mjs"`(Node ≥ 22.8),或逐个跑
|
|
155
157
|
> `node test/parse.test.mjs`、`node test/pricing.test.mjs`、`node test/pricing-store.test.mjs`、
|
|
156
158
|
> `node test/client-layout.test.mjs`、`node test/host-route.test.mjs`。
|
|
159
|
+
>
|
|
160
|
+
> 两种偶发失败都属于环境限制,不是插件行为,逐文件运行可稳定复现通过:
|
|
161
|
+
> - `host-route` 的"合并写回"用例依赖点击时的 `FORCED_GAP_MS`(30s)节流门;多个测试文件
|
|
162
|
+
> 共用同一进程(`--test-isolation=none`)时那条"强制同步"可能被门挡掉。
|
|
163
|
+
> - Windows 上原子写(写 `.tmp` 后 `rename`)可能被安全软件短暂占用而报
|
|
164
|
+
> `EPERM ... rename`;重跑即过。
|
|
165
|
+
>
|
|
166
|
+
> 另:`test/host-route.test.mjs` 与 `test/pricing-store.test.mjs` 都只需要一个可写的临时目录
|
|
167
|
+
> (`os.tmpdir()`),若该目录不可写(`mkdtemp ... EPERM`),把 `TEMP`/`TMP` 指到任意可写目录即可。
|
|
157
168
|
|
|
158
169
|
## Uninstall / 卸载
|
|
159
170
|
|
package/lib/client.js
CHANGED
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
// Cordis 面板按钮下方)。轮询宿主路由 `/api/deepseek-usage`(见 lib/index.js)
|
|
5
5
|
// 每 5 分钟一次,点击卡片任意位置可立即刷新;还没拿到余额(宿主刚重启/接口刚起来)
|
|
6
6
|
// 时按 QUICK_RETRY_MS 阶梯快速补几次请求,卡片几秒内收敛。
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
7
|
+
// 两种形态:
|
|
8
|
+
// · 侧边栏展开——完整卡片:余额(放大显示,符号随币种 ¥/$)+ 当前模型档单价
|
|
9
|
+
// (输入/输入缓存/输出,图标 + 数字,位于卡片右下角)+ 峰谷指示灯(右上角,
|
|
10
|
+
// 只有颜色)+ 距下次峰谷切换的倒计时(`2d 15h` / `5h 47m` / `23m`,与指示灯同行、位于其左侧)。
|
|
11
|
+
// · 侧边栏折叠——36px 图标栏里只有峰谷指示灯(见下方 `if (!wide)` 分支)。
|
|
10
12
|
//
|
|
11
13
|
// 设计约束(用户只关心"我还能花多少、这会儿什么价"):
|
|
12
14
|
// · 插件的内部信息——计价来源、同步状态、价格表文件名与路径、模型改名——一律
|
|
@@ -27,9 +29,11 @@ window.__ModuleLoader__.load({
|
|
|
27
29
|
// ---- constants -------------------------------------------------
|
|
28
30
|
const POLL_MS = 5 * 60 * 1000;
|
|
29
31
|
const USAGE_PATH = "/api/deepseek-usage";
|
|
30
|
-
// 常态卡片高度:上下 padding 8+
|
|
31
|
-
//
|
|
32
|
-
|
|
32
|
+
// 常态卡片高度:上下 padding 8+16 + 金额行 minHeight 28 + 边框 2 = 54。
|
|
33
|
+
// 底部多留的 8px 是为了让倒计时那一行与下方单价行之间有呼吸感。
|
|
34
|
+
// 倒计时与圆点都在金额行内定位,不额外增高(无头 Chromium 实测 cardH=54)。
|
|
35
|
+
// 异常态把卡片置空时用它兜住同一个高度,侧边栏高度不跳动。
|
|
36
|
+
const CARD_MIN_HEIGHT = 54;
|
|
33
37
|
// 卡片还没拿到余额时的快速重试节奏(宿主刚重启、接口刚起来、或本次请求失败):
|
|
34
38
|
// 否则要等满 5 分钟轮询才会从空卡片变成真实数字。
|
|
35
39
|
const QUICK_RETRY_MS = [4000, 8000, 15000, 30000];
|
|
@@ -312,6 +316,8 @@ window.__ModuleLoader__.load({
|
|
|
312
316
|
load(true);
|
|
313
317
|
};
|
|
314
318
|
|
|
319
|
+
// 折叠态(图标栏):内容宽 36px(侧边栏 56px − 折叠态左右各 10px 内边距),
|
|
320
|
+
// 只容得下峰谷指示灯。指示灯仍是"点击刷新"的落点。
|
|
315
321
|
if (!wide) {
|
|
316
322
|
return h("div", {
|
|
317
323
|
style: {
|
|
@@ -326,15 +332,10 @@ window.__ModuleLoader__.load({
|
|
|
326
332
|
display: "flex",
|
|
327
333
|
flexDirection: "row",
|
|
328
334
|
alignItems: "center",
|
|
329
|
-
gap: 5,
|
|
330
335
|
userSelect: "none",
|
|
331
336
|
},
|
|
332
337
|
onClick: () => load(true),
|
|
333
|
-
},
|
|
334
|
-
h("span", { style: { display: "inline-flex", alignItems: "baseline", gap: 3 } },
|
|
335
|
-
h("span", { style: { fontWeight: 700, fontSize: 13, color: C.label } }, symbol),
|
|
336
|
-
h("span", { style: { fontWeight: 700, fontSize: 13, color: C.label } }, money(balance && balance.total))),
|
|
337
|
-
h("span", { style: dot }));
|
|
338
|
+
}, h("span", { style: dot }));
|
|
338
339
|
}
|
|
339
340
|
|
|
340
341
|
// 只有"余额类错误"(未配置 Key / 余额接口或网络失败)才走到这里:卡片置空、
|
|
@@ -342,7 +343,7 @@ window.__ModuleLoader__.load({
|
|
|
342
343
|
// (CARD_MIN_HEIGHT),侧边栏不跳动;文字多行时卡片自然变高。
|
|
343
344
|
// 注意:这里不显示任何插件内部信息(来源、同步时间、价格表路径),历史上那批
|
|
344
345
|
// 良性提示已随"去技术化"一起删除。
|
|
345
|
-
//
|
|
346
|
+
// 折叠态(!wide)早在上面就返回了:它只有峰谷指示灯,没有文字空间。
|
|
346
347
|
if (blanked) {
|
|
347
348
|
return h("div", {
|
|
348
349
|
style: {
|
|
@@ -382,7 +383,9 @@ window.__ModuleLoader__.load({
|
|
|
382
383
|
boxSizing: "border-box",
|
|
383
384
|
flex: "1 1 100%",
|
|
384
385
|
minWidth: 0,
|
|
385
|
-
|
|
386
|
+
// 上 8 下 10(配合单价行 bottom:2,这组是用户看过后选定的观感)。
|
|
387
|
+
// 顶部保持 8px 不动,圆点才能继续紧贴右上角。
|
|
388
|
+
padding: "8px 10px 12px",
|
|
386
389
|
borderRadius: 10,
|
|
387
390
|
border: "1px solid " + C.border,
|
|
388
391
|
background: C.bg,
|
|
@@ -399,35 +402,44 @@ window.__ModuleLoader__.load({
|
|
|
399
402
|
},
|
|
400
403
|
onClick: onCardClick,
|
|
401
404
|
},
|
|
402
|
-
//
|
|
403
|
-
//
|
|
404
|
-
|
|
405
|
+
// 金额行:余额 + 右侧「倒计时 + 峰谷圆点」。
|
|
406
|
+
// 倒计时与圆点放在同一个 flex 行里、alignItems:center,两者圆心必然重合;
|
|
407
|
+
// 整组 alignSelf:flex-start + 负 margin,让圆点距卡片顶/右各 8px。
|
|
408
|
+
// 两个反面做法都试过并实测过:
|
|
409
|
+
// · alignSelf:center → 圆点被压到卡片中线,不再是"右上角";
|
|
410
|
+
// · paddingTop:6 → 金额行被撑高,卡片被撑大,圆点反而更靠下。
|
|
411
|
+
// 倒计时 minWidth:0 + overflow:hidden:窄侧边栏下先省略号截断,不挤压余额
|
|
412
|
+
// (实测 "2d 23h" 在 170px 宽的卡片里仍放得下)。
|
|
413
|
+
h("div", { style: { display: "flex", alignItems: "baseline", minHeight: 28, minWidth: 0, gap: 6 } },
|
|
405
414
|
h("span", { style: { fontWeight: 700, fontSize: 24, color: C.label, lineHeight: "28px", marginRight: 3 } }, symbol),
|
|
406
|
-
h("span", { style: { fontWeight: 700, fontSize: 24, color: C.label, lineHeight: "28px" } }, money(balance && balance.total))
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
style: {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
415
|
+
h("span", { style: { fontWeight: 700, fontSize: 24, color: C.label, lineHeight: "28px" } }, money(balance && balance.total)),
|
|
416
|
+
// 负 margin 只挪动整组,不改变金额行高度(卡片高度由内边距决定)。
|
|
417
|
+
// 实测:marginTop -4 与 marginRight -3 时,圆点距卡片顶、右各 8px
|
|
418
|
+
// (右侧不能按"内边距 10 − 8"去推,内边距本就含在行宽里)。
|
|
419
|
+
h("span", { style: { display: "flex", alignItems: "center", gap: 6, minWidth: 0, marginLeft: "auto", flex: "0 1 auto", alignSelf: "flex-start", marginTop: -4, marginRight: -3 } },
|
|
420
|
+
// 倒计时:距下次峰谷切换的剩余时间(`2d 15h` / `5h 47m` / `23m` / `switching`)。
|
|
421
|
+
// 纯英文单位、无前缀,中英界面一致。
|
|
422
|
+
// 字号/字重刻意与右下角单价数字对齐(继承卡片正文 12px、fontWeight 600),
|
|
423
|
+
// 让右上角这行和右下角单价行是同一套文字样式。
|
|
424
|
+
h("span", {
|
|
425
|
+
style: {
|
|
426
|
+
fontWeight: 600,
|
|
427
|
+
color: C.sub,
|
|
428
|
+
minWidth: 0,
|
|
429
|
+
overflow: "hidden",
|
|
430
|
+
textOverflow: "ellipsis",
|
|
431
|
+
whiteSpace: "nowrap",
|
|
432
|
+
},
|
|
433
|
+
}, countdown),
|
|
434
|
+
// 峰谷指示灯:只有颜色(橙=高峰 / 绿=空闲),没有 title、没有其他文字。
|
|
435
|
+
h("span", { style: dot }))),
|
|
426
436
|
// 底部行:只剩当前档单价,恒靠右下角。
|
|
437
|
+
// 这组 bottom:2 + 卡片下内边距 10 是用户看过多组对比后选定的观感(价格略微下移、
|
|
438
|
+
// 下方不再空一大块)。注意绝对定位的行不参与卡片高度计算,改内边距时两者要一起看。
|
|
427
439
|
// 用 flex-end 而不是 space-between:容器只有一个子元素时 space-between 会把它
|
|
428
440
|
// 推到最左侧(0.6.0 的回归点)。
|
|
429
441
|
h("span", {
|
|
430
|
-
style: { position: "absolute", left: 9, right: 9, bottom:
|
|
442
|
+
style: { position: "absolute", left: 9, right: 9, bottom: 2, display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 6 },
|
|
431
443
|
},
|
|
432
444
|
h("span", { style: { display: "inline-flex", alignItems: "center", gap: 5, flex: "none" } },
|
|
433
445
|
Price(h(IconIn, null), t("price.input"), tier && tier.input),
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dougen/dsh-deepseek-usage",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "DeepSeek 余额侧边栏插件:余额(官方 API)、当前档单价与峰谷时段指示灯,支持中/英文界面。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/dougen/dsh-deepseek-usage.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/dougen/dsh-deepseek-usage",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/dougen/dsh-deepseek-usage/issues"
|
|
14
|
+
},
|
|
7
15
|
"scripts": {
|
|
8
16
|
"test": "node --test test/",
|
|
9
17
|
"check:pricing": "node lib/pricing-remote.js --check"
|