@kenz1117/dsh-ui-usage-billing 1.0.42 → 1.0.44
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/lib/client.js +5 -5
- package/lib/index.js +125 -38
- package/lib/types/aggregate.d.ts +1 -1
- package/lib/types/client/UsageBilling.d.ts +13 -0
- package/lib/types/client/locales.d.ts +1 -1
- package/lib/types/client/pricing.d.ts +8 -15
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -238,6 +238,36 @@ const PEAK_ERA_START_MS = Date.parse("2026-08-16T16:00:00Z");
|
|
|
238
238
|
*/
|
|
239
239
|
const WEEKEND_OFFPEAK_START_MS = Date.parse("2026-08-22T16:00:00Z");
|
|
240
240
|
/**
|
|
241
|
+
* flash 系调价分界(UTC 2026-09-10T04:00:00Z,即北京时间 2026-09-10 12:00):
|
|
242
|
+
* 官方自此刻起 V4 Flash / V4 Flash Vision (Exp) 调价——谷档 1.5/0.05/4.5 →
|
|
243
|
+
* 1/0.02/4(峰 = 谷 × 2)。目录条目写现行(新)价;分界前的历史事件由
|
|
244
|
+
* {@link computeCostAt} 按 {@link FLASH_REPRICED_OFFPEAK} 回算旧价,与
|
|
245
|
+
* {@link PEAK_ERA_START_MS} 同一「按事件时刻分段适用规则」口径。
|
|
246
|
+
*/
|
|
247
|
+
const FLASH_REPRICE_MS = Date.parse("2026-09-10T04:00:00Z");
|
|
248
|
+
/**
|
|
249
|
+
* flash 系调价前的官方谷档价(CNY / 1M tokens):{@link FLASH_REPRICE_MS}
|
|
250
|
+
* 之前的 flash / flash-vision-exp 事件按此回算(峰档 = 谷档 × 2)。pro 的
|
|
251
|
+
* 同表条目是 V4 Pro 峰谷时代刊例(谷 4.5/0.15/13.5):官方公告自
|
|
252
|
+
* {@link FLASH_REPRICE_MS} 起 V4 Pro 请求全部路由至 V4.1 Flash 并按其单价
|
|
253
|
+
* 计费(V4.1 Pro 上线前),故分界前回算 V4 Pro 刊例、分界后走目录的 Flash 价。
|
|
254
|
+
* 用户价 = 实付价,与 legacy 口径相同地跳过本表。
|
|
255
|
+
*/
|
|
256
|
+
const FLASH_PRE_REPRICE_BAND = {
|
|
257
|
+
input: 1.5,
|
|
258
|
+
cacheHit: .05,
|
|
259
|
+
output: 4.5
|
|
260
|
+
};
|
|
261
|
+
const FLASH_REPRICED_OFFPEAK = {
|
|
262
|
+
flash: FLASH_PRE_REPRICE_BAND,
|
|
263
|
+
"flash-vision-exp": FLASH_PRE_REPRICE_BAND,
|
|
264
|
+
pro: {
|
|
265
|
+
input: 4.5,
|
|
266
|
+
cacheHit: .15,
|
|
267
|
+
output: 13.5
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
/**
|
|
241
271
|
* DeepSeek V4 峰谷时代之前的官方基础价(CNY / 1M tokens):官方中文定价页
|
|
242
272
|
* 峰谷改版前的基础价档(缓存写沿用历史规则按命中价计)。键为内置目录键,
|
|
243
273
|
* flash-vision-exp 与 flash 同价。仅当事件时刻早于 {@link PEAK_ERA_START_MS}
|
|
@@ -300,6 +330,8 @@ function isBeijingWeekend(timeMs) {
|
|
|
300
330
|
* splits peak (09:00-12:00 / 14:00-18:00 Beijing) at 2x the off-peak rate
|
|
301
331
|
* from 2026-08-17, and Gemini's Flex tier discounts spare-capacity traffic.
|
|
302
332
|
*/
|
|
333
|
+
/** DeepSeek 官方高峰时段说明(峰谷分时计费目录条目共用)。 */
|
|
334
|
+
const DEEPSEEK_PEAK_HOURS = "09:00-12:00 / 14:00-18:00";
|
|
303
335
|
const MODEL_CATALOG = [
|
|
304
336
|
{
|
|
305
337
|
key: "flash",
|
|
@@ -308,16 +340,16 @@ const MODEL_CATALOG = [
|
|
|
308
340
|
colorVar: "dsw-static-blue-500",
|
|
309
341
|
price: {
|
|
310
342
|
currency: "CNY",
|
|
311
|
-
input:
|
|
312
|
-
cacheHit: .
|
|
313
|
-
output:
|
|
343
|
+
input: 2,
|
|
344
|
+
cacheHit: .04,
|
|
345
|
+
output: 8,
|
|
314
346
|
offPeak: {
|
|
315
|
-
input: 1
|
|
316
|
-
cacheHit: .
|
|
317
|
-
output: 4
|
|
347
|
+
input: 1,
|
|
348
|
+
cacheHit: .02,
|
|
349
|
+
output: 4
|
|
318
350
|
}
|
|
319
351
|
},
|
|
320
|
-
peakHours:
|
|
352
|
+
peakHours: DEEPSEEK_PEAK_HOURS
|
|
321
353
|
},
|
|
322
354
|
{
|
|
323
355
|
key: "flash-vision-exp",
|
|
@@ -326,16 +358,16 @@ const MODEL_CATALOG = [
|
|
|
326
358
|
colorVar: "dsw-static-blue-500",
|
|
327
359
|
price: {
|
|
328
360
|
currency: "CNY",
|
|
329
|
-
input:
|
|
330
|
-
cacheHit: .
|
|
331
|
-
output:
|
|
361
|
+
input: 2,
|
|
362
|
+
cacheHit: .04,
|
|
363
|
+
output: 8,
|
|
332
364
|
offPeak: {
|
|
333
|
-
input: 1
|
|
334
|
-
cacheHit: .
|
|
335
|
-
output: 4
|
|
365
|
+
input: 1,
|
|
366
|
+
cacheHit: .02,
|
|
367
|
+
output: 4
|
|
336
368
|
}
|
|
337
369
|
},
|
|
338
|
-
peakHours:
|
|
370
|
+
peakHours: DEEPSEEK_PEAK_HOURS
|
|
339
371
|
},
|
|
340
372
|
{
|
|
341
373
|
key: "pro",
|
|
@@ -344,16 +376,16 @@ const MODEL_CATALOG = [
|
|
|
344
376
|
colorVar: "dsw-static-deepseek-500",
|
|
345
377
|
price: {
|
|
346
378
|
currency: "CNY",
|
|
347
|
-
input:
|
|
348
|
-
cacheHit: .
|
|
349
|
-
output:
|
|
379
|
+
input: 2,
|
|
380
|
+
cacheHit: .04,
|
|
381
|
+
output: 8,
|
|
350
382
|
offPeak: {
|
|
351
|
-
input:
|
|
352
|
-
cacheHit: .
|
|
353
|
-
output:
|
|
383
|
+
input: 1,
|
|
384
|
+
cacheHit: .02,
|
|
385
|
+
output: 4
|
|
354
386
|
}
|
|
355
387
|
},
|
|
356
|
-
peakHours:
|
|
388
|
+
peakHours: DEEPSEEK_PEAK_HOURS
|
|
357
389
|
},
|
|
358
390
|
{
|
|
359
391
|
key: "glm",
|
|
@@ -1388,6 +1420,7 @@ const MODEL_CATALOG = [
|
|
|
1388
1420
|
const MODEL_KEY_ALIASES = {
|
|
1389
1421
|
"deepseek-v4-flash": "flash",
|
|
1390
1422
|
"deepseek-v4-flash-vision-exp": "flash-vision-exp",
|
|
1423
|
+
"deepseek-v4.1-flash": "flash",
|
|
1391
1424
|
"deepseek-v4-pro": "pro",
|
|
1392
1425
|
"glm-5.2": "glm",
|
|
1393
1426
|
"glm-4.5-air": "glm-4.5-air",
|
|
@@ -1725,6 +1758,12 @@ function computeCostAt(entry, buckets, timeMs, peakShare = DEFAULT_PEAK_SHARE) {
|
|
|
1725
1758
|
const priced = applyPromo(entry, timeMs);
|
|
1726
1759
|
const legacy = timeMs < PEAK_ERA_START_MS && entry.userPriced !== true ? LEGACY_DEEPSEEK_BANDS[entry.key] : void 0;
|
|
1727
1760
|
if (legacy !== void 0) return priceBandCost(legacy, buckets, "CNY");
|
|
1761
|
+
const repriced = timeMs < FLASH_REPRICE_MS && entry.userPriced !== true ? FLASH_REPRICED_OFFPEAK[entry.key] : void 0;
|
|
1762
|
+
if (repriced !== void 0) return priceBandCost((timeMs < WEEKEND_OFFPEAK_START_MS ? tariffV1At(timeMs) : tierAt(timeMs)) === "peak" ? {
|
|
1763
|
+
input: repriced.input * 2,
|
|
1764
|
+
cacheHit: repriced.cacheHit * 2,
|
|
1765
|
+
output: repriced.output * 2
|
|
1766
|
+
} : repriced, buckets, "CNY");
|
|
1728
1767
|
if (priced.price.offPeak === void 0) return priceBandCost(priced.price, buckets, priced.price.currency);
|
|
1729
1768
|
return priceBandCost((timeMs < WEEKEND_OFFPEAK_START_MS ? tariffV1At(timeMs) : tierAt(timeMs)) === "peak" ? priced.price : priced.price.offPeak, buckets, priced.price.currency);
|
|
1730
1769
|
}
|
|
@@ -2459,7 +2498,7 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
2459
2498
|
id,
|
|
2460
2499
|
...cwd === void 0 ? {} : { cwd },
|
|
2461
2500
|
...stamp === null ? {} : { stamp },
|
|
2462
|
-
foldVersion:
|
|
2501
|
+
foldVersion: 12,
|
|
2463
2502
|
fingerprint: foldFingerprint,
|
|
2464
2503
|
fold: serializeFold(fold)
|
|
2465
2504
|
};
|
|
@@ -2556,7 +2595,7 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
2556
2595
|
try {
|
|
2557
2596
|
const cwd = meta.cwd;
|
|
2558
2597
|
const ledgerRow = ledger.get(id);
|
|
2559
|
-
if (ledgerRow !== void 0 && ledgerRow.stamp !== void 0 && stamp !== null && ledgerRow.stamp === stamp && (ledgerRow.foldVersion ?? 1) ===
|
|
2598
|
+
if (ledgerRow !== void 0 && ledgerRow.stamp !== void 0 && stamp !== null && ledgerRow.stamp === stamp && (ledgerRow.foldVersion ?? 1) === 12 && ledgerRow.fingerprint === foldFingerprint) {
|
|
2560
2599
|
const fold = deserializeFold(ledgerRow.fold);
|
|
2561
2600
|
folds.push({
|
|
2562
2601
|
id,
|
|
@@ -2638,7 +2677,7 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
2638
2677
|
for (const entry of ledger.values()) {
|
|
2639
2678
|
if (included.has(entry.id)) continue;
|
|
2640
2679
|
try {
|
|
2641
|
-
const stale = (entry.foldVersion ?? 1) <
|
|
2680
|
+
const stale = (entry.foldVersion ?? 1) < 12 || entry.fingerprint !== foldFingerprint;
|
|
2642
2681
|
folds.push({
|
|
2643
2682
|
id: entry.id,
|
|
2644
2683
|
...entry.cwd === void 0 ? {} : { cwd: entry.cwd },
|
|
@@ -5714,13 +5753,7 @@ function apply(ctx, config = {}) {
|
|
|
5714
5753
|
const now = Date.now();
|
|
5715
5754
|
if (now - lastSnapshotAt < SNAPSHOT_INTERVAL_MS) return;
|
|
5716
5755
|
lastSnapshotAt = now;
|
|
5717
|
-
const payload = JSON.stringify(
|
|
5718
|
-
...doc,
|
|
5719
|
-
_writer: {
|
|
5720
|
-
pid: process.pid,
|
|
5721
|
-
at: now
|
|
5722
|
-
}
|
|
5723
|
-
});
|
|
5756
|
+
const payload = JSON.stringify(doc);
|
|
5724
5757
|
(async () => {
|
|
5725
5758
|
try {
|
|
5726
5759
|
const existing = await readFile(snapshotPath, "utf8");
|
|
@@ -5744,13 +5777,67 @@ function apply(ctx, config = {}) {
|
|
|
5744
5777
|
} catch {}
|
|
5745
5778
|
return null;
|
|
5746
5779
|
};
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5780
|
+
const notifyClaimsPath = `${snapshotPath}.notify-claims.json`;
|
|
5781
|
+
const notifyClaims = {
|
|
5782
|
+
loaded: false,
|
|
5783
|
+
keys: []
|
|
5784
|
+
};
|
|
5785
|
+
ctx.effect(() => ctx.webServer.register({
|
|
5786
|
+
kind: "exact",
|
|
5787
|
+
path: "/api/billing/notify-claim",
|
|
5788
|
+
handler: async (req, res) => {
|
|
5789
|
+
if (!guardLoopback(req, res)) return;
|
|
5790
|
+
if (req.method !== "POST") {
|
|
5791
|
+
res.writeHead(405, { "content-type": "application/json; charset=utf-8" });
|
|
5792
|
+
res.end(JSON.stringify({ error: "method not allowed" }));
|
|
5793
|
+
return;
|
|
5794
|
+
}
|
|
5795
|
+
if (!isLoopbackOrigin(req.headers.origin) || !(req.headers["content-type"] ?? "").toLowerCase().includes("application/json")) {
|
|
5796
|
+
res.writeHead(403, { "content-type": "application/json; charset=utf-8" });
|
|
5797
|
+
res.end(JSON.stringify({ error: "forbidden: loopback only" }));
|
|
5798
|
+
return;
|
|
5799
|
+
}
|
|
5800
|
+
try {
|
|
5801
|
+
let body = "";
|
|
5802
|
+
for await (const chunk of req) {
|
|
5803
|
+
body += String(chunk);
|
|
5804
|
+
if (body.length > 2048) {
|
|
5805
|
+
res.end(JSON.stringify({ error: "body too large" }));
|
|
5806
|
+
return;
|
|
5807
|
+
}
|
|
5808
|
+
}
|
|
5809
|
+
const parsed = JSON.parse(body === "" ? "{}" : body);
|
|
5810
|
+
if (typeof parsed.key !== "string" || parsed.key === "" || parsed.key.length > 200) {
|
|
5811
|
+
res.writeHead(400, { "content-type": "application/json; charset=utf-8" });
|
|
5812
|
+
res.end(JSON.stringify({ error: "invalid key" }));
|
|
5813
|
+
return;
|
|
5814
|
+
}
|
|
5815
|
+
if (!notifyClaims.loaded) {
|
|
5816
|
+
notifyClaims.loaded = true;
|
|
5817
|
+
try {
|
|
5818
|
+
const stored = JSON.parse(await readFile(notifyClaimsPath, "utf8"));
|
|
5819
|
+
if (Array.isArray(stored.keys)) notifyClaims.keys = stored.keys.filter((k) => typeof k === "string");
|
|
5820
|
+
} catch {}
|
|
5821
|
+
}
|
|
5822
|
+
if (notifyClaims.keys.includes(parsed.key)) {
|
|
5823
|
+
res.writeHead(200, { "content-type": "application/json; charset=utf-8" });
|
|
5824
|
+
res.end(JSON.stringify({ claimed: false }));
|
|
5825
|
+
return;
|
|
5826
|
+
}
|
|
5827
|
+
notifyClaims.keys.push(parsed.key);
|
|
5828
|
+
if (notifyClaims.keys.length > 400) notifyClaims.keys = notifyClaims.keys.slice(-200);
|
|
5829
|
+
writeFileAtomic(notifyClaimsPath, JSON.stringify({ keys: notifyClaims.keys }), {
|
|
5830
|
+
mode: 384,
|
|
5831
|
+
dirMode: 448
|
|
5832
|
+
}).catch(() => {});
|
|
5833
|
+
res.writeHead(200, { "content-type": "application/json; charset=utf-8" });
|
|
5834
|
+
res.end(JSON.stringify({ claimed: true }));
|
|
5835
|
+
} catch {
|
|
5836
|
+
res.writeHead(400, { "content-type": "application/json; charset=utf-8" });
|
|
5837
|
+
res.end(JSON.stringify({ error: "invalid" }));
|
|
5838
|
+
}
|
|
5839
|
+
}
|
|
5840
|
+
}), "usage-billing: notify-claim route");
|
|
5754
5841
|
ctx.inject(["settings"], (sctx) => {
|
|
5755
5842
|
const scope = sctx.settings.register(usageBillingSettingsNs, UsageBillingSettingsSchema, { base: { enableUsageStatsTool: config.enableUsageStatsTool ?? false } });
|
|
5756
5843
|
usageSettingsScope = scope;
|
package/lib/types/aggregate.d.ts
CHANGED
|
@@ -478,7 +478,7 @@ export interface UsageLedgerDocument {
|
|
|
478
478
|
* 会话费用只剩最近一段,issue #29)。
|
|
479
479
|
* 持久账本行据此区分新旧算法:日志已删/不可读而只能沿用旧行时,UI 标注置信度提示。
|
|
480
480
|
*/
|
|
481
|
-
export declare const FOLD_VERSION =
|
|
481
|
+
export declare const FOLD_VERSION = 12;
|
|
482
482
|
/**
|
|
483
483
|
* 一次性账本迁移:id 唯一,apply 在加载边界对原始文档执行,已应用过的跳过。
|
|
484
484
|
* 未来账本/schema 字段变更(重命名、拆桶、语义调整)时,在此追加一条迁移并
|
|
@@ -84,6 +84,15 @@ export declare function projectMonthCost(byDay: Record<string, {
|
|
|
84
84
|
* @returns 重估后的文档;无用户价或缺 byDayModels 时原样返回。
|
|
85
85
|
*/
|
|
86
86
|
export declare function recostWithUserPrices(stats: UsageStats): UsageStats;
|
|
87
|
+
/**
|
|
88
|
+
* 跨实例提醒认领后发系统通知(issue #44):多实例(CLI + 桌面等)合法共存,
|
|
89
|
+
* 各自轮询会重复弹通知。两级去重——进程内 Set 挡同进程的并发/重渲染(trigger
|
|
90
|
+
* 与仪表盘是两个组件实例,effect 同周期并发时本地 store 标记读到的还是旧值);
|
|
91
|
+
* 跨进程走宿主认领端点(先到先得),另一实例刚发过则跳过。端点不可达(旧版本/
|
|
92
|
+
* 网络故障)时放行,退化为原有 per-客户端去重。通知构造失败(平台限制)静默。
|
|
93
|
+
* Set 导出供测试重置(模块级状态会跨用例泄漏)。
|
|
94
|
+
*/
|
|
95
|
+
export declare const notifiedKeys: Set<string>;
|
|
87
96
|
/** 近 7 天费用序列(含今天,缺日补 0):触发卡 hover 速览的迷你柱数据源。
|
|
88
97
|
* 导出供测试:纯函数(日期取本地时区)。 */
|
|
89
98
|
export declare function activeDaysOf(byDay: Record<string, {
|
|
@@ -126,6 +135,10 @@ interface SessionBillingRow {
|
|
|
126
135
|
calls: number;
|
|
127
136
|
cost: number;
|
|
128
137
|
lastActive: number;
|
|
138
|
+
/** 展示层合并标记(issue #42):同标题会话归并后的段数(>1 时行尾显示 ×N)。 */
|
|
139
|
+
mergedCount?: number;
|
|
140
|
+
/** 合并组的段明细(展示层专用):一级行默认收起,展开后逐段显示。合并函数需 push,故非 readonly。 */
|
|
141
|
+
children?: SessionBillingRow[];
|
|
129
142
|
}
|
|
130
143
|
/** Usage stats structure from `.dsh-usage-stats.json`. */
|
|
131
144
|
export interface UsageStats {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Locale dictionaries for the usage billing surface. */
|
|
2
|
-
export type UsageBillingKey = 'title' | 'cost' | 'todayCost' | 'monthCost' | 'yearCost' | 'monthProjected' | 'liveTurn' | 'liveSession' | 'calls' | 'cacheHitRate' | 'tokens' | 'inputTokens' | 'outputTokens' | 'avgCost' | 'trend' | 'trend7d' | 'trend30d' | 'trendMetric' | 'trendMetricCost' | 'trendMetricTokens' | 'trendEmpty' | 'budget' | 'budgetAmount' | 'budgetSummary' | 'sessions' | 'sessionTitle' | 'lastActive' | 'sessionOverflow' | 'budgetTierBody' | 'models' | 'providerBilling' | 'channelUnknown' | 'actual' | 'pricing' | 'input' | 'output' | 'cacheHit' | 'peak' | 'offPeak' | 'flat' | 'band' | 'close' | 'footer' | 'footerCredit' | 'lastUpdated' | 'noData' | 'todayRate' | 'rateLive' | 'rateBuiltin' | 'promoBadge' | 'promoUntil' | 'promoOpenEnded' | 'pricingTip' | 'pricingUnit' | 'pricingNotes' | 'ubPeak' | 'ubOff' | 'ubStd' | 'peakBand' | 'pricingSource' | 'noteCache' | 'noteBand' | 'noteSource' | 'balance' | 'balanceUnconfigured' | 'balanceUnauthorized' | 'balanceUnreachable' | 'uncatalogued' | 'estimatedPricing' | 'balanceDays' | 'balanceLowBody' | 'reconcileDrift' | 'reconcileDismiss' | 'subscriptionNotConfigured' | 'subscriptionUnauthorized' | 'subscriptionUnavailable' | 'subscriptionInvalid' | 'subscriptionRateLimited' | 'subscriptionSession' | 'subscriptionWeekly' | 'subscriptionMonthly' | 'subscriptionBilling' | 'subscriptionRemaining' | 'subscriptionExhausted' | 'subscriptionReset' | 'subscriptionNoApi' | 'floatWindow' | 'floatModeCombined' | 'floatModeSubscription' | 'floatMode' | 'floatTargets' | 'floatWindowHint' | 'floatNoTargets' | 'floatNoTargetsHint' | 'cardDisplay' | 'cardDisplayHint' | 'cardMetric' | 'cardMetricMoney' | 'cardMetricTokens' | 'triggerMonthTokens' | 'subscriptionsStale' | 'staleLedgerNotice' | 'tokenCacheWrite' | 'toolRank' | 'toolName' | 'userPrices' | 'userPricesHint' | 'userPriceSave' | 'userPriceModel' | 'userPriceSource' | 'userPriceSourceHint' | 'userPriceOffPeak' | 'userPriceNormal' | 'userPriceCurrency' | 'userPriceAdd' | 'userPriceRemoveSelected' | 'userPriceSelect' | 'sessionStaleBadge' | 'heatmapLess' | 'heatmapMore' | 'currency' | 'currencyCny' | 'currencyUsd' | 'heatmap' | 'rounds' | 'roundsHint' | 'anomaly' | '
|
|
2
|
+
export type UsageBillingKey = 'title' | 'cost' | 'todayCost' | 'monthCost' | 'yearCost' | 'monthProjected' | 'liveTurn' | 'liveSession' | 'calls' | 'cacheHitRate' | 'tokens' | 'inputTokens' | 'outputTokens' | 'avgCost' | 'trend' | 'trend7d' | 'trend30d' | 'trendMetric' | 'trendMetricCost' | 'trendMetricTokens' | 'trendEmpty' | 'budget' | 'budgetAmount' | 'budgetSummary' | 'sessions' | 'sessionTitle' | 'lastActive' | 'sessionOverflow' | 'budgetTierBody' | 'models' | 'providerBilling' | 'channelUnknown' | 'actual' | 'pricing' | 'input' | 'output' | 'cacheHit' | 'peak' | 'offPeak' | 'flat' | 'band' | 'close' | 'footer' | 'footerCredit' | 'lastUpdated' | 'noData' | 'todayRate' | 'rateLive' | 'rateBuiltin' | 'promoBadge' | 'promoUntil' | 'promoOpenEnded' | 'pricingTip' | 'pricingUnit' | 'pricingNotes' | 'ubPeak' | 'ubOff' | 'ubStd' | 'peakBand' | 'pricingSource' | 'noteCache' | 'noteBand' | 'noteSource' | 'balance' | 'balanceUnconfigured' | 'balanceUnauthorized' | 'balanceUnreachable' | 'uncatalogued' | 'estimatedPricing' | 'balanceDays' | 'balanceLowBody' | 'reconcileDrift' | 'reconcileDismiss' | 'subscriptionNotConfigured' | 'subscriptionUnauthorized' | 'subscriptionUnavailable' | 'subscriptionInvalid' | 'subscriptionRateLimited' | 'subscriptionSession' | 'subscriptionWeekly' | 'subscriptionMonthly' | 'subscriptionBilling' | 'subscriptionRemaining' | 'subscriptionExhausted' | 'subscriptionReset' | 'subscriptionNoApi' | 'floatWindow' | 'floatModeCombined' | 'floatModeSubscription' | 'floatMode' | 'floatTargets' | 'floatWindowHint' | 'floatNoTargets' | 'floatNoTargetsHint' | 'cardDisplay' | 'cardDisplayHint' | 'cardMetric' | 'cardMetricMoney' | 'cardMetricTokens' | 'triggerMonthTokens' | 'subscriptionsStale' | 'staleLedgerNotice' | 'tokenCacheWrite' | 'toolRank' | 'toolName' | 'userPrices' | 'userPricesHint' | 'userPriceSave' | 'userPriceModel' | 'userPriceSource' | 'userPriceSourceHint' | 'userPriceOffPeak' | 'userPriceNormal' | 'userPriceCurrency' | 'userPriceAdd' | 'userPriceRemoveSelected' | 'userPriceSelect' | 'sessionStaleBadge' | 'sessionUntitled' | 'heatmapLess' | 'heatmapMore' | 'currency' | 'currencyCny' | 'currencyUsd' | 'heatmap' | 'rounds' | 'roundsHint' | 'anomaly' | 'model' | 'thModel' | 'thInputMiss' | 'thInputHit' | 'costAbbr' | 'tabOverview' | 'tabTrends' | 'tabProviders' | 'tabPricing' | 'tabSettings' | 'budgetHint' | 'peakAlertHint' | 'peakAlertDescPeak' | 'peakAlertDescOff' | 'export' | 'exportCsvDay' | 'exportCsvSession' | 'exportJson' | 'peakShare' | 'peakSharePerCall' | 'offPeakSavings' | 'perfMax' | 'weekCost' | 'roleCost' | 'roleUser' | 'roleAssistant' | 'roleTool' | 'roleHint' | 'tierPeak' | 'tierOff' | 'tierToPeak' | 'tierToOff' | 'tierAlertEnterPeak' | 'tierAlertEnterOff' | 'peakAlertTitlePeak' | 'peakAlertTitleOff' | 'peakAlert' | 'peakAlertLeadMin' | 'peakAlertPos' | 'peakAlertMode' | 'peakAlertPosCorner' | 'peakAlertPosCenter' | 'peakAlertModePeak' | 'peakAlertModeOff' | 'peakAlertModeBoth' | 'peakAlertWebNotify' | 'peakAlertPreview' | 'planTypeCode' | 'planTypeToken' | 'subscriptionFeePerMonth' | 'triggerToday' | 'triggerMonth' | 'subscriptionIncluded' | 'free' | 'official' | 'thirdParty' | 'perfSamples' | 'perfTtft' | 'perfP50' | 'perfP90' | 'perfTps' | 'perfLatency' | 'perfEstimated' | 'perfEmpty' | 'perfTpsUnit' | 'perfTitle' | 'perfHint' | 'perfAll' | 'perfChartEmpty' | 'heatmapYear' | 'heatmapMonth' | 'activeDays' | 'streakDays' | 'subscriptionAutoDetect' | 'pluginAuthor' | 'pluginRepository' | 'pluginNpm' | 'pluginLicense' | 'tabToken' | 'tokenExport' | 'tokenExportCsv' | 'tokenCacheHitRate' | 'tokenReasoningShare' | 'tokenReasoningShort' | 'tokenIo' | 'tokenPeak' | 'tokenDaily' | 'tokenByModel' | 'tokenMiss' | 'tokenHit' | 'tokenOutput' | 'tokenViewStructure' | 'tokenViewModel' | 'tokenHitShort' | 'tokenMissShort' | 'tokenTotal' | 'tokenShare' | 'usageStatsTool' | 'usageStatsToolHint' | 'balanceGranted' | 'balanceTopped' | 'balanceDaily' | 'balanceDaysLong' | 'balanceDaysUnit' | 'popTodayModel' | 'popNoConsumption' | 'popTitle' | 'popDirectLead' | 'popSubLead' | 'unpricedHint' | 'searchEstimateHint' | 'siteListDisplay' | 'siteListDisplayHint' | 'liveCostBar' | 'liveCostBarHint' | 'liveCostBarPosition' | 'liveCostBarPosBelow' | 'liveCostBarPosAbove' | 'liveCostBarPosToolbar' | 'exportCsvSite' | 'panelRelayQuota' | 'relayBalance' | 'relayNoQuota' | 'relayWindowUsed' | 'relayKindNewApi' | 'relayKindSub2Api' | 'relayKindUnknown';
|
|
3
3
|
export declare const NS = "usageBilling";
|
|
4
4
|
export declare const zh: Record<UsageBillingKey, string>;
|
|
5
5
|
export declare const en: Record<UsageBillingKey, string>;
|
|
@@ -153,6 +153,14 @@ export declare const PEAK_ERA_START_MS: number;
|
|
|
153
153
|
* 档位判定按事件所在时段适用各自的规则,不得统一套现行规则重算历史。
|
|
154
154
|
*/
|
|
155
155
|
export declare const WEEKEND_OFFPEAK_START_MS: number;
|
|
156
|
+
/**
|
|
157
|
+
* flash 系调价分界(UTC 2026-09-10T04:00:00Z,即北京时间 2026-09-10 12:00):
|
|
158
|
+
* 官方自此刻起 V4 Flash / V4 Flash Vision (Exp) 调价——谷档 1.5/0.05/4.5 →
|
|
159
|
+
* 1/0.02/4(峰 = 谷 × 2)。目录条目写现行(新)价;分界前的历史事件由
|
|
160
|
+
* {@link computeCostAt} 按 {@link FLASH_REPRICED_OFFPEAK} 回算旧价,与
|
|
161
|
+
* {@link PEAK_ERA_START_MS} 同一「按事件时刻分段适用规则」口径。
|
|
162
|
+
*/
|
|
163
|
+
export declare const FLASH_REPRICE_MS: number;
|
|
156
164
|
/** 计费时段档位:高峰 / 空闲(官方 DeepSeek 刊例价:高峰 = 空闲 × 2)。 */
|
|
157
165
|
export type PriceTierId = 'peak' | 'offPeak';
|
|
158
166
|
/** 成本显示币种:人民币(国内模型直价)/ 美元(国外模型直价或换算显示)。 */
|
|
@@ -299,21 +307,6 @@ export interface ModelEntry {
|
|
|
299
307
|
/** 该条目当前按用户自定义单价计价(设置面板可维护);费率表标注「自定义」。 */
|
|
300
308
|
userPriced?: boolean;
|
|
301
309
|
}
|
|
302
|
-
/**
|
|
303
|
-
* Built-in catalog of current mainstream models as of 2026-08-16, priced from
|
|
304
|
-
* each provider's official price page. Domestic providers are OpenAI-API
|
|
305
|
-
* compatible and publish RMB prices directly; overseas providers publish USD
|
|
306
|
-
* and convert through the exchange rate at estimate time. Retired models
|
|
307
|
-
* (GPT-4o family, Gemini 2.x, GLM-4.x-lite, older Qwen) are deliberately
|
|
308
|
-
* absent, as are Anthropic Claude models (their native API is not
|
|
309
|
-
* OpenAI-compatible, so the harness cannot drive them directly). DeepSeek
|
|
310
|
-
* keys match the harness stats file so real usage prices from the catalog;
|
|
311
|
-
* unknown keys fall back to `other`.
|
|
312
|
-
*
|
|
313
|
-
* Time-of-day billing (peak/off-peak) is now real: DeepSeek V4 officially
|
|
314
|
-
* splits peak (09:00-12:00 / 14:00-18:00 Beijing) at 2x the off-peak rate
|
|
315
|
-
* from 2026-08-17, and Gemini's Flex tier discounts spare-capacity traffic.
|
|
316
|
-
*/
|
|
317
310
|
export declare const MODEL_CATALOG: readonly ModelEntry[];
|
|
318
311
|
/**
|
|
319
312
|
* 真实 provider model id → 计费目录键(`MODEL_CATALOG[].key`)的映射。未知 id
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kenz1117/dsh-ui-usage-billing",
|
|
3
3
|
"description": "Usage billing dashboard for DeepSeek Harness: sidebar cost metrics plus a full dashboard modal, priced from a current multi-provider catalog with real usage aggregated from session logs.",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.44",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
7
7
|
"deepseek",
|