@kenz1117/dsh-ui-usage-billing 1.0.18 → 1.0.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 +5 -15
- package/README.md +7 -17
- package/lib/client.js +5 -5
- package/lib/index.js +85 -15
- package/lib/types/aggregate.d.ts +10 -7
- package/lib/types/balance.d.ts +6 -0
- package/lib/types/client/PerfPanel.d.ts +10 -8
- package/lib/types/client/heatmap.d.ts +1 -1
- package/lib/types/client/locales.d.ts +1 -1
- package/lib/types/client/pricing.d.ts +21 -0
- package/lib/types/client/round-chart.d.ts +1 -1
- package/lib/types/client/usage-billing-settings.d.ts +20 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -210,6 +210,44 @@ function currentRate() {
|
|
|
210
210
|
/** Default share of traffic assumed to fall in the peak band (0..1). */
|
|
211
211
|
const DEFAULT_PEAK_SHARE = .5;
|
|
212
212
|
/**
|
|
213
|
+
* 峰谷计价时代分界(UTC 2026-08-16T16:00:00Z,即北京时间 2026-08-17 00:00):
|
|
214
|
+
* DeepSeek V4 自此起按峰/谷两档计价。此前官方只有基础价一档——历史事件若
|
|
215
|
+
* 套现行峰/谷档价会把成本高估约 50%(谷价 = 基础价 × 1.5)。半开区间:该
|
|
216
|
+
* 时刻及之后按峰谷档计。
|
|
217
|
+
*/
|
|
218
|
+
const PEAK_ERA_START_MS = Date.parse("2026-08-16T16:00:00Z");
|
|
219
|
+
/**
|
|
220
|
+
* 周末全谷规则分界(UTC 2026-08-22T16:00:00Z,即北京时间 2026-08-23 00:00):
|
|
221
|
+
* 官方自此刻起周六/周日全天不区分峰谷(高峰时段收窄为工作日);生效前的
|
|
222
|
+
* 周末仍按 v1 峰谷规则(周六日 9-12 / 14-18 同样是高峰时段)。历史事件的
|
|
223
|
+
* 档位判定按事件所在时段适用各自的规则,不得统一套现行规则重算历史。
|
|
224
|
+
*/
|
|
225
|
+
const WEEKEND_OFFPEAK_START_MS = Date.parse("2026-08-22T16:00:00Z");
|
|
226
|
+
/**
|
|
227
|
+
* DeepSeek V4 峰谷时代之前的官方基础价(CNY / 1M tokens):官方中文定价页
|
|
228
|
+
* 峰谷改版前的基础价档(缓存写沿用历史规则按命中价计)。键为内置目录键,
|
|
229
|
+
* flash-vision-exp 与 flash 同价。仅当事件时刻早于 {@link PEAK_ERA_START_MS}
|
|
230
|
+
* 且条目未被用户价覆盖(用户价是实付价,优先于一切内置口径)时启用;
|
|
231
|
+
* 币种固定 CNY——内置 DeepSeek 目录即人民币刊例,不随 live 覆盖漂移。
|
|
232
|
+
*/
|
|
233
|
+
const LEGACY_DEEPSEEK_BANDS = {
|
|
234
|
+
flash: {
|
|
235
|
+
input: 1,
|
|
236
|
+
cacheHit: .02,
|
|
237
|
+
output: 2
|
|
238
|
+
},
|
|
239
|
+
"flash-vision-exp": {
|
|
240
|
+
input: 1,
|
|
241
|
+
cacheHit: .02,
|
|
242
|
+
output: 2
|
|
243
|
+
},
|
|
244
|
+
pro: {
|
|
245
|
+
input: 3,
|
|
246
|
+
cacheHit: .025,
|
|
247
|
+
output: 6
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
/**
|
|
213
251
|
* 工作日高峰时段判定(北京时间,UTC+8,无夏令时):09:00–12:00、14:00–18:00。
|
|
214
252
|
* 周末(周六/周日)北京全天为低谷,不调用本函数判定峰/平。
|
|
215
253
|
* @param beijingHour - 北京时间的小时数(0–23)。
|
|
@@ -1597,10 +1635,25 @@ function computeCost(entry, buckets, peakShare = DEFAULT_PEAK_SHARE, nowMs = Dat
|
|
|
1597
1635
|
return peak * peakShare + off * (1 - peakShare);
|
|
1598
1636
|
}
|
|
1599
1637
|
/**
|
|
1638
|
+
* v1 峰谷档判定(峰谷开闸起、周末全谷分界止):不豁免周末——该时段官方
|
|
1639
|
+
* 高峰时段为每天 9-12 / 14-18(周六日同样计峰)。仅用于历史事件计费;
|
|
1640
|
+
* 「当前时刻」的档位(提醒/时段条/费率展示)一律走 {@link tierAt} 现行规则。
|
|
1641
|
+
*/
|
|
1642
|
+
function tariffV1At(timeMs) {
|
|
1643
|
+
return isPeakHour((new Date(timeMs).getUTCHours() + 8) % 24) ? "peak" : "offPeak";
|
|
1644
|
+
}
|
|
1645
|
+
/**
|
|
1600
1646
|
* 按调用时刻精确判定高峰/空闲档并计价(P0-1:替代固定比例混合)。时刻未知
|
|
1601
1647
|
* (null/NaN,理论不发生在真实事件流)时回退 {@link DEFAULT_PEAK_SHARE} 混合,
|
|
1602
1648
|
* 保持旧语义不低估。平档模型(无 offPeak)两个时段同价。限时促销与峰谷档
|
|
1603
1649
|
* 同口径:按事件时刻判定该笔流量当时享受的单价。
|
|
1650
|
+
*
|
|
1651
|
+
* 历史正确性(按变更节点分段适用规则,不统一套现行价重算历史):
|
|
1652
|
+
* - 早于 {@link PEAK_ERA_START_MS} 的事件按当时官方基础价
|
|
1653
|
+
* ({@link LEGACY_DEEPSEEK_BANDS})计费;
|
|
1654
|
+
* - 峰谷开闸至 {@link WEEKEND_OFFPEAK_START_MS} 之间按 v1 规则(周末不豁免,
|
|
1655
|
+
* 周六日 9-12 / 14-18 计峰);
|
|
1656
|
+
* - 周末全谷分界起按现行规则({@link tierAt},周六日全天低谷)。
|
|
1604
1657
|
* @param entry - the catalog entry whose prices apply.
|
|
1605
1658
|
* @param buckets - token usage counts.
|
|
1606
1659
|
* @param timeMs - the call's wall-clock time (epoch ms); null falls back to the peak-share mix.
|
|
@@ -1610,8 +1663,10 @@ function computeCost(entry, buckets, peakShare = DEFAULT_PEAK_SHARE, nowMs = Dat
|
|
|
1610
1663
|
function computeCostAt(entry, buckets, timeMs, peakShare = DEFAULT_PEAK_SHARE) {
|
|
1611
1664
|
if (timeMs === null || timeMs === void 0 || !Number.isFinite(timeMs)) return computeCost(entry, buckets, peakShare);
|
|
1612
1665
|
const priced = applyPromo(entry, timeMs);
|
|
1666
|
+
const legacy = timeMs < PEAK_ERA_START_MS && entry.userPriced !== true ? LEGACY_DEEPSEEK_BANDS[entry.key] : void 0;
|
|
1667
|
+
if (legacy !== void 0) return priceBandCost(legacy, buckets, "CNY");
|
|
1613
1668
|
if (priced.price.offPeak === void 0) return priceBandCost(priced.price, buckets, priced.price.currency);
|
|
1614
|
-
return priceBandCost(tierAt(timeMs) === "peak" ? priced.price : priced.price.offPeak, buckets, priced.price.currency);
|
|
1669
|
+
return priceBandCost((timeMs < WEEKEND_OFFPEAK_START_MS ? tariffV1At(timeMs) : tierAt(timeMs)) === "peak" ? priced.price : priced.price.offPeak, buckets, priced.price.currency);
|
|
1615
1670
|
}
|
|
1616
1671
|
/**
|
|
1617
1672
|
* Format an amount with adaptive precision and the given currency symbol.
|
|
@@ -2342,7 +2397,7 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
2342
2397
|
id,
|
|
2343
2398
|
...meta.cwd === void 0 ? {} : { cwd: meta.cwd },
|
|
2344
2399
|
...stamp === null ? {} : { stamp },
|
|
2345
|
-
foldVersion:
|
|
2400
|
+
foldVersion: 6,
|
|
2346
2401
|
fold: serializeFold(fold)
|
|
2347
2402
|
};
|
|
2348
2403
|
const previous = ledger.get(id);
|
|
@@ -2366,7 +2421,7 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
2366
2421
|
for (const entry of ledger.values()) {
|
|
2367
2422
|
if (included.has(entry.id)) continue;
|
|
2368
2423
|
try {
|
|
2369
|
-
const stale = (entry.foldVersion ?? 1) <
|
|
2424
|
+
const stale = (entry.foldVersion ?? 1) < 6;
|
|
2370
2425
|
folds.push({
|
|
2371
2426
|
id: entry.id,
|
|
2372
2427
|
...entry.cwd === void 0 ? {} : { cwd: entry.cwd },
|
|
@@ -2412,7 +2467,7 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
2412
2467
|
outputCost: 0
|
|
2413
2468
|
};
|
|
2414
2469
|
const perfModel = /* @__PURE__ */ new Map();
|
|
2415
|
-
const
|
|
2470
|
+
const perfHourModel = /* @__PURE__ */ new Map();
|
|
2416
2471
|
for (const { id: sessionId, cwd, fold, staleLedger } of folds) {
|
|
2417
2472
|
mergeUsageInto(total, fold.total);
|
|
2418
2473
|
roles.userChars += fold.roles.userChars;
|
|
@@ -2443,13 +2498,18 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
2443
2498
|
if (sample.tps !== void 0) modelAccum.tps.push(sample.tps);
|
|
2444
2499
|
if (sample.latencyMs !== void 0) modelAccum.latencies.push(sample.latencyMs);
|
|
2445
2500
|
if (sample.estimated) modelAccum.estimated += 1;
|
|
2446
|
-
let
|
|
2501
|
+
let hourModels = perfHourModel.get(sample.hour);
|
|
2502
|
+
if (hourModels === void 0) {
|
|
2503
|
+
hourModels = /* @__PURE__ */ new Map();
|
|
2504
|
+
perfHourModel.set(sample.hour, hourModels);
|
|
2505
|
+
}
|
|
2506
|
+
let hourAccum = hourModels.get(sample.model);
|
|
2447
2507
|
if (hourAccum === void 0) {
|
|
2448
2508
|
hourAccum = {
|
|
2449
2509
|
ttfts: [],
|
|
2450
2510
|
tps: []
|
|
2451
2511
|
};
|
|
2452
|
-
|
|
2512
|
+
hourModels.set(sample.model, hourAccum);
|
|
2453
2513
|
}
|
|
2454
2514
|
hourAccum.ttfts.push(sample.ttftMs);
|
|
2455
2515
|
if (sample.tps !== void 0) hourAccum.tps.push(sample.tps);
|
|
@@ -2509,14 +2569,14 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
2509
2569
|
latencyAvg: acc.latencies.length === 0 ? 0 : mean(acc.latencies),
|
|
2510
2570
|
estimatedSamples: acc.estimated
|
|
2511
2571
|
}])),
|
|
2512
|
-
|
|
2572
|
+
byHourModel: Object.fromEntries([...perfHourModel].map(([hour, models]) => [hour, Object.fromEntries([...models].map(([model, acc]) => [model, {
|
|
2513
2573
|
samples: acc.ttfts.length,
|
|
2514
2574
|
ttftAvg: mean(acc.ttfts),
|
|
2515
2575
|
...acc.tps.length === 0 ? {} : { tpsAvg: mean(acc.tps) }
|
|
2516
|
-
}]))
|
|
2576
|
+
}]))]))
|
|
2517
2577
|
};
|
|
2518
2578
|
lastDoc = {
|
|
2519
|
-
version:
|
|
2579
|
+
version: 4,
|
|
2520
2580
|
updatedAt: now,
|
|
2521
2581
|
source: "session-logs",
|
|
2522
2582
|
timezone: hostTimeZone(),
|
|
@@ -3198,18 +3258,28 @@ function evalExtract(rule, data) {
|
|
|
3198
3258
|
}
|
|
3199
3259
|
return base;
|
|
3200
3260
|
}
|
|
3201
|
-
/**
|
|
3261
|
+
/**
|
|
3262
|
+
* 请求头占位符解析:值中任意位置的 `{{ENV_NAME}}` 经凭据 seam 替换(如
|
|
3263
|
+
* `Bearer {{KEY}}`、`token={{KEY}}`、一处多占位符);被引用的任一凭据缺失
|
|
3264
|
+
* 或为空 → 返回 null(fail-closed,与完整占位符形态的历史语义一致)。
|
|
3265
|
+
*/
|
|
3202
3266
|
async function resolveHeaders(ctx, headers) {
|
|
3203
3267
|
const resolved = {};
|
|
3204
3268
|
for (const [key, value] of Object.entries(headers)) {
|
|
3205
|
-
const
|
|
3206
|
-
if (
|
|
3269
|
+
const matches = [...value.matchAll(/\{\{([A-Z0-9_]+)\}\}/gi)];
|
|
3270
|
+
if (matches.length === 0) {
|
|
3207
3271
|
resolved[key] = value;
|
|
3208
3272
|
continue;
|
|
3209
3273
|
}
|
|
3210
|
-
const
|
|
3211
|
-
|
|
3212
|
-
|
|
3274
|
+
const hits = /* @__PURE__ */ new Map();
|
|
3275
|
+
for (const m of matches) {
|
|
3276
|
+
const name = m[1] ?? "";
|
|
3277
|
+
if (hits.has(name)) continue;
|
|
3278
|
+
const hit = await ctx.credentials.resolve(credentialRef(name));
|
|
3279
|
+
if (hit === void 0 || hit.value === "") return null;
|
|
3280
|
+
hits.set(name, hit.value);
|
|
3281
|
+
}
|
|
3282
|
+
resolved[key] = value.replace(/\{\{([A-Z0-9_]+)\}\}/gi, (raw, name) => hits.get(name) ?? raw);
|
|
3213
3283
|
}
|
|
3214
3284
|
return resolved;
|
|
3215
3285
|
}
|
package/lib/types/aggregate.d.ts
CHANGED
|
@@ -236,8 +236,8 @@ export interface RoleCost {
|
|
|
236
236
|
export interface PerfStats {
|
|
237
237
|
/** 按模型聚合(键 = 计费目录键;未收录模型原样保留)。 */
|
|
238
238
|
byModel: Record<string, ModelPerf>;
|
|
239
|
-
/**
|
|
240
|
-
|
|
239
|
+
/** 按小时×模型聚合(外键 = {@link hourStamp},内键 = 模型目录键;北京时间)。 */
|
|
240
|
+
byHourModel: Record<string, Record<string, HourModelPerf>>;
|
|
241
241
|
}
|
|
242
242
|
/** 一个模型的性能统计:首字延时均值 / P50 / P90、生成速度均值、总延迟均值。 */
|
|
243
243
|
export interface ModelPerf {
|
|
@@ -260,11 +260,11 @@ export interface ModelPerf {
|
|
|
260
260
|
/** 以 step/start 估算的样本数(工具续写步骤无独立 request/header)。 */
|
|
261
261
|
estimatedSamples: number;
|
|
262
262
|
}
|
|
263
|
-
/**
|
|
264
|
-
export interface
|
|
263
|
+
/** 一个小时单模型的性能统计(外键 = {@link hourStamp},内键 = 模型目录键)。 */
|
|
264
|
+
export interface HourModelPerf {
|
|
265
265
|
samples: number;
|
|
266
266
|
ttftAvg: number;
|
|
267
|
-
/** 平均生成速度(tokens/s
|
|
267
|
+
/** 平均生成速度(tokens/s);该小时该模型无可测生成窗口时缺失。 */
|
|
268
268
|
tpsAvg?: number;
|
|
269
269
|
}
|
|
270
270
|
/** 会话明细行:仪表盘「会话明细」面板的数据源。 */
|
|
@@ -420,10 +420,13 @@ export interface UsageLedgerDocument {
|
|
|
420
420
|
* 两次 header 之间的用量串到上一个模型,订阅模型首当其冲,issue #14);v2 =
|
|
421
421
|
* `assistant/message` 自带 source 归账(1.0.7 起);v3 = 联网搜索请求按次估算
|
|
422
422
|
* 计费(issue #15,1.0.9 起);v4 = 模型×日期×站点三维桶(issue #16,按 origin
|
|
423
|
-
* 绑定自定义价的显示层重估)——旧行缺该维度,按无 origin
|
|
423
|
+
* 绑定自定义价的显示层重估)——旧行缺该维度,按无 origin 价处理;v5 = 峰谷
|
|
424
|
+
* 时代之前(2026-08-16T16:00Z)的 DeepSeek 事件按当时基础价计费(v4 把全部
|
|
425
|
+
* 历史套现行峰/谷档价,高估约 50%);v6 = v1 峰谷窗口(至 2026-08-22T16:00Z)
|
|
426
|
+
* 的周末不豁免峰时(v5 错套现行周末全谷规则,低估该窗口周六日的峰时费用)。
|
|
424
427
|
* 持久账本行据此区分新旧算法:日志已删/不可读而只能沿用旧行时,UI 标注置信度提示。
|
|
425
428
|
*/
|
|
426
|
-
export declare const FOLD_VERSION =
|
|
429
|
+
export declare const FOLD_VERSION = 6;
|
|
427
430
|
/**
|
|
428
431
|
* 一次性账本迁移:id 唯一,apply 在加载边界对原始文档执行,已应用过的跳过。
|
|
429
432
|
* 未来账本/schema 字段变更(重命名、拆桶、语义调整)时,在此追加一条迁移并
|
package/lib/types/balance.d.ts
CHANGED
|
@@ -52,6 +52,12 @@ export declare function pickRemainingQuota(source: unknown): number | undefined;
|
|
|
52
52
|
* @returns 数值;取不到或结果非有限数返回 undefined。
|
|
53
53
|
*/
|
|
54
54
|
export declare function evalExtract(rule: CustomBalanceExtract, data: unknown): number | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* 请求头占位符解析:值中任意位置的 `{{ENV_NAME}}` 经凭据 seam 替换(如
|
|
57
|
+
* `Bearer {{KEY}}`、`token={{KEY}}`、一处多占位符);被引用的任一凭据缺失
|
|
58
|
+
* 或为空 → 返回 null(fail-closed,与完整占位符形态的历史语义一致)。
|
|
59
|
+
*/
|
|
60
|
+
export declare function resolveHeaders(ctx: Context, headers: Record<string, string>): Promise<Record<string, string> | null>;
|
|
55
61
|
/**
|
|
56
62
|
* 查询自定义 Provider 余额(插件 config 的 `customBalances`)。每个条目独立
|
|
57
63
|
* 成败:占位符凭据缺失 → unconfigured;401/403 → unauthorized;网络或提取
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* PerfPanel: per-model latency/perf table + per-hour
|
|
2
|
+
* PerfPanel: per-model latency/perf table + per-hour per-model comparison curve.
|
|
3
3
|
*
|
|
4
4
|
* Reads the optional `perf` field of the usage-stats document (aggregated by
|
|
5
5
|
* the host from session logs). Renders a per-model table of TTFT mean/P50/P90,
|
|
6
6
|
* generation speed, total latency and estimated-step count, plus a small
|
|
7
|
-
* dependency-free SVG
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* dependency-free SVG hourly curve: one colored polyline per lit model with a
|
|
8
|
+
* metric tab (TTFT ms / tok/s) and clickable model chips; hovering snaps to the
|
|
9
|
+
* nearest hour and shows a crosshair + tooltip listing every lit model's value.
|
|
10
|
+
* Absent `perf` renders an empty state; the panel never fabricates samples.
|
|
10
11
|
*/
|
|
11
12
|
import type { TrendSeriesModel } from './TrendChart.tsx';
|
|
12
13
|
import type { UsageBillingKey } from './locales.ts';
|
|
@@ -24,8 +25,8 @@ export interface PerfModelData {
|
|
|
24
25
|
latencyAvg: number;
|
|
25
26
|
estimatedSamples: number;
|
|
26
27
|
}
|
|
27
|
-
/**
|
|
28
|
-
export interface
|
|
28
|
+
/** 小时×模型性能统计(与服务端 `HourModelPerf` 同形)。 */
|
|
29
|
+
export interface PerfHourModelData {
|
|
29
30
|
samples: number;
|
|
30
31
|
ttftAvg: number;
|
|
31
32
|
tpsAvg?: number;
|
|
@@ -33,12 +34,13 @@ export interface PerfHourData {
|
|
|
33
34
|
/** 性能指标文档(服务端可选 `perf` 字段;旧快照缺失)。 */
|
|
34
35
|
export interface ClientPerf {
|
|
35
36
|
byModel: Record<string, PerfModelData>;
|
|
36
|
-
|
|
37
|
+
/** 小时 → 模型 → 小时统计;旧 host 文档缺失时图表区按空态兜底。 */
|
|
38
|
+
byHourModel: Record<string, Record<string, PerfHourModelData>>;
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
41
|
* Render the performance panel.
|
|
40
42
|
* @param props.perf - the optional perf doc; `undefined`/empty renders an empty state.
|
|
41
|
-
* @param props.models - model legend (key/name/color) for the table swatches and curve
|
|
43
|
+
* @param props.models - model legend (key/name/color) for the table swatches and curve chips.
|
|
42
44
|
* @param props.t - locale function.
|
|
43
45
|
*/
|
|
44
46
|
export declare function PerfPanel({ perf, models, t, }: {
|
|
@@ -32,6 +32,6 @@ export declare function UsageHeatmap({ days, currency, now, t, range }: {
|
|
|
32
32
|
currency: CostCurrency;
|
|
33
33
|
now?: Date;
|
|
34
34
|
range?: 'month' | 'year';
|
|
35
|
-
t: (key: '
|
|
35
|
+
t: (key: 'costAbbr' | 'noData' | 'heatmapLess' | 'heatmapMore') => string;
|
|
36
36
|
}): React.ReactNode;
|
|
37
37
|
//# sourceMappingURL=heatmap.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Locale dictionaries for the usage billing surface. */
|
|
2
|
-
export type UsageBillingKey = '
|
|
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' | 'project' | 'lastActive' | 'sessionOverflow' | 'budgetTierBody' | 'models' | 'providerBilling' | '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' | 'userPriceCurrency' | 'userPriceAdd' | 'userPriceRemove' | 'sessionStaleBadge' | 'heatmapLess' | 'heatmapMore' | 'currency' | 'currencyCny' | 'currencyUsd' | 'heatmap' | 'rounds' | 'roundsHint' | 'anomaly' | 'workspaces' | 'workspacesHint' | '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' | 'pluginVersion' | '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' | '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>;
|
|
@@ -133,6 +133,20 @@ export declare function getRateInfo(): {
|
|
|
133
133
|
};
|
|
134
134
|
/** Default share of traffic assumed to fall in the peak band (0..1). */
|
|
135
135
|
export declare const DEFAULT_PEAK_SHARE = 0.5;
|
|
136
|
+
/**
|
|
137
|
+
* 峰谷计价时代分界(UTC 2026-08-16T16:00:00Z,即北京时间 2026-08-17 00:00):
|
|
138
|
+
* DeepSeek V4 自此起按峰/谷两档计价。此前官方只有基础价一档——历史事件若
|
|
139
|
+
* 套现行峰/谷档价会把成本高估约 50%(谷价 = 基础价 × 1.5)。半开区间:该
|
|
140
|
+
* 时刻及之后按峰谷档计。
|
|
141
|
+
*/
|
|
142
|
+
export declare const PEAK_ERA_START_MS: number;
|
|
143
|
+
/**
|
|
144
|
+
* 周末全谷规则分界(UTC 2026-08-22T16:00:00Z,即北京时间 2026-08-23 00:00):
|
|
145
|
+
* 官方自此刻起周六/周日全天不区分峰谷(高峰时段收窄为工作日);生效前的
|
|
146
|
+
* 周末仍按 v1 峰谷规则(周六日 9-12 / 14-18 同样是高峰时段)。历史事件的
|
|
147
|
+
* 档位判定按事件所在时段适用各自的规则,不得统一套现行规则重算历史。
|
|
148
|
+
*/
|
|
149
|
+
export declare const WEEKEND_OFFPEAK_START_MS: number;
|
|
136
150
|
/** 计费时段档位:高峰 / 空闲(官方 DeepSeek 刊例价:高峰 = 空闲 × 2)。 */
|
|
137
151
|
export type PriceTierId = 'peak' | 'offPeak';
|
|
138
152
|
/** 成本显示币种:人民币(国内模型直价)/ 美元(国外模型直价或换算显示)。 */
|
|
@@ -369,6 +383,13 @@ export declare function computeCost(entry: ModelEntry, buckets: TokenUsageBucket
|
|
|
369
383
|
* (null/NaN,理论不发生在真实事件流)时回退 {@link DEFAULT_PEAK_SHARE} 混合,
|
|
370
384
|
* 保持旧语义不低估。平档模型(无 offPeak)两个时段同价。限时促销与峰谷档
|
|
371
385
|
* 同口径:按事件时刻判定该笔流量当时享受的单价。
|
|
386
|
+
*
|
|
387
|
+
* 历史正确性(按变更节点分段适用规则,不统一套现行价重算历史):
|
|
388
|
+
* - 早于 {@link PEAK_ERA_START_MS} 的事件按当时官方基础价
|
|
389
|
+
* ({@link LEGACY_DEEPSEEK_BANDS})计费;
|
|
390
|
+
* - 峰谷开闸至 {@link WEEKEND_OFFPEAK_START_MS} 之间按 v1 规则(周末不豁免,
|
|
391
|
+
* 周六日 9-12 / 14-18 计峰);
|
|
392
|
+
* - 周末全谷分界起按现行规则({@link tierAt},周六日全天低谷)。
|
|
372
393
|
* @param entry - the catalog entry whose prices apply.
|
|
373
394
|
* @param buckets - token usage counts.
|
|
374
395
|
* @param timeMs - the call's wall-clock time (epoch ms); null falls back to the peak-share mix.
|
|
@@ -32,6 +32,6 @@ export declare function RoundCostChart({ rounds, flags, currency, t }: {
|
|
|
32
32
|
rounds: readonly RoundChartRow[];
|
|
33
33
|
flags: readonly AnomalyFlag[];
|
|
34
34
|
currency: CostCurrency;
|
|
35
|
-
t: (key: '
|
|
35
|
+
t: (key: 'model' | 'costAbbr') => string;
|
|
36
36
|
}): React.ReactNode;
|
|
37
37
|
//# sourceMappingURL=round-chart.d.ts.map
|
|
@@ -107,4 +107,24 @@ export declare const USER_PRICES_STORAGE_KEY = "dsh.ui-usage-billing.prices";
|
|
|
107
107
|
export declare function loadUserPrices(): UserPriceMap;
|
|
108
108
|
/** 写入用户自定义价。失败静默(展示偏好非关键)。 */
|
|
109
109
|
export declare function saveUserPrices(prices: UserPriceMap): void;
|
|
110
|
+
/** 性能曲线的指标视角。 */
|
|
111
|
+
export type PerfMetric = 'ttft' | 'tps';
|
|
112
|
+
/**
|
|
113
|
+
* 性能面板的视图偏好:当前指标 tab 与点亮的模型曲线集合。
|
|
114
|
+
* 纯 client 偏好,存 localStorage(不依赖 node 半区接口/设置 schema)。
|
|
115
|
+
*/
|
|
116
|
+
export interface PerfViewPrefs {
|
|
117
|
+
/** 当前指标:首字延时(ms)/ 生成速度(tok/s)。 */
|
|
118
|
+
metric: PerfMetric;
|
|
119
|
+
/** 点亮的模型键列表;缺省 = 按样本数前 5(用户未碰过图例时跟随默认)。 */
|
|
120
|
+
models?: string[];
|
|
121
|
+
}
|
|
122
|
+
/** 默认性能视图偏好:首字延时 tab;模型集合跟随默认(前 5)。 */
|
|
123
|
+
export declare const DEFAULT_PERF_VIEW_PREFS: PerfViewPrefs;
|
|
124
|
+
/** localStorage key(与其他 `dsh.ui-usage-billing.*` 偏好同命名空间)。 */
|
|
125
|
+
export declare const PERF_VIEW_STORAGE_KEY = "dsh.ui-usage-billing.perf";
|
|
126
|
+
/** 读取性能视图偏好(含损坏/缺失回退到默认)。仅在浏览器半区调用。 */
|
|
127
|
+
export declare function loadPerfViewPrefs(): PerfViewPrefs;
|
|
128
|
+
/** 写入性能视图偏好。失败静默(展示偏好非关键)。 */
|
|
129
|
+
export declare function savePerfViewPrefs(prefs: PerfViewPrefs): void;
|
|
110
130
|
//# sourceMappingURL=usage-billing-settings.d.ts.map
|
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.20",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|