@kenz1117/dsh-ui-usage-billing 1.5.0 → 1.5.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 +2 -1
- package/lib/client.js +4 -4
- package/lib/index.js +67 -5
- package/lib/types/aggregate.d.ts +31 -0
- package/lib/types/client/UsageBilling.d.ts +11 -0
- package/lib/types/client/export.d.ts +7 -1
- package/lib/types/client/live-cost.d.ts +13 -3
- package/lib/types/client/locales.d.ts +1 -1
- package/lib/types/client/usage-billing-settings.d.ts +3 -1
- package/package.json +33 -31
package/lib/index.js
CHANGED
|
@@ -2301,7 +2301,9 @@ const BUILTIN_MODEL_KEY_ALIASES = {
|
|
|
2301
2301
|
"deepseek-v4.1-flash": "flash",
|
|
2302
2302
|
"deepseek-v4.1-flash-expires-on-0910": "flash",
|
|
2303
2303
|
"deepseek-flash": "flash",
|
|
2304
|
+
"deepseek-v4.1-flash-1017": "flash",
|
|
2304
2305
|
"deepseek/deepseek-v4.1-flash": "flash",
|
|
2306
|
+
"deepseek/deepseek-v4.1-flash-1017": "flash",
|
|
2305
2307
|
"deepseek/deepseek-flash": "flash",
|
|
2306
2308
|
"deepseek/deepseek-v4-pro": "pro",
|
|
2307
2309
|
"deepseek-v4-pro": "pro",
|
|
@@ -2733,6 +2735,57 @@ function workspaceNameOf(cwd) {
|
|
|
2733
2735
|
if (cwd === void 0 || cwd === "") return "—";
|
|
2734
2736
|
return cwd.split(/[\\/]/).filter(Boolean).at(-1) ?? "—";
|
|
2735
2737
|
}
|
|
2738
|
+
/**
|
|
2739
|
+
* 从会话 header 提取子智能体归并标记(直接父会话 id):`origin: "subagent"`
|
|
2740
|
+
* (宿主的产品分类)或 `delegationDepth > 0`(持久化委派深度)任一命中即视为
|
|
2741
|
+
* 子会话。子会话但 header 无 parentSession(异常数据)返回 undefined——无法
|
|
2742
|
+
* 归位就按顶层会话处理,保守不标。导出供测试。
|
|
2743
|
+
*/
|
|
2744
|
+
function subParentOf(meta) {
|
|
2745
|
+
if (meta.origin !== "subagent" && !((meta.delegationDepth ?? 0) > 0)) return void 0;
|
|
2746
|
+
const parent = meta.parentSession;
|
|
2747
|
+
return typeof parent === "string" && parent !== "" ? parent : void 0;
|
|
2748
|
+
}
|
|
2749
|
+
/**
|
|
2750
|
+
* 给会话行补后代合计(subCost/subCalls):按 parentId 建子索引,对每行递归
|
|
2751
|
+
* 汇总全部后代子会话(多级委派整链计入根对话)。纯展示层归因——不改任何
|
|
2752
|
+
* 总额桶(子会话费用本就在 total/byDay/byModel 里,行级只是拆出来给人看)。
|
|
2753
|
+
* 环引用(异常数据)按 visited 跳过,不死循环。原地修改传入行。导出供测试。
|
|
2754
|
+
*/
|
|
2755
|
+
function foldSubagentFamilies(rows) {
|
|
2756
|
+
const subsOf = /* @__PURE__ */ new Map();
|
|
2757
|
+
for (const row of rows) {
|
|
2758
|
+
const parent = row.parentId;
|
|
2759
|
+
if (parent === void 0) continue;
|
|
2760
|
+
const list = subsOf.get(parent);
|
|
2761
|
+
if (list !== void 0) list.push(row);
|
|
2762
|
+
else subsOf.set(parent, [row]);
|
|
2763
|
+
}
|
|
2764
|
+
const familyOf = (id, visited) => {
|
|
2765
|
+
let cost = 0;
|
|
2766
|
+
let calls = 0;
|
|
2767
|
+
for (const child of subsOf.get(id) ?? []) {
|
|
2768
|
+
if (visited.has(child.id)) continue;
|
|
2769
|
+
visited.add(child.id);
|
|
2770
|
+
cost += child.cost;
|
|
2771
|
+
calls += child.calls;
|
|
2772
|
+
const nested = familyOf(child.id, visited);
|
|
2773
|
+
cost += nested.cost;
|
|
2774
|
+
calls += nested.calls;
|
|
2775
|
+
}
|
|
2776
|
+
return {
|
|
2777
|
+
cost,
|
|
2778
|
+
calls
|
|
2779
|
+
};
|
|
2780
|
+
};
|
|
2781
|
+
for (const row of rows) {
|
|
2782
|
+
const family = familyOf(row.id, /* @__PURE__ */ new Set([row.id]));
|
|
2783
|
+
if (family.calls > 0) {
|
|
2784
|
+
row.subCalls = family.calls;
|
|
2785
|
+
if (family.cost > 0) row.subCost = family.cost;
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2736
2789
|
/** TTFT 尖峰阈值(毫秒):超过计为一次尖峰样本,用于定位服务端抖动。 */
|
|
2737
2790
|
const PERF_SPIKE_MS = 1e4;
|
|
2738
2791
|
/** 全零摘要(合并的恒等元)。 */
|
|
@@ -3533,11 +3586,12 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
3533
3586
|
* 价目表变化后未受影响行(无 unpriced 模型)依旧零读取复用。 */
|
|
3534
3587
|
const foldNeedsReprice = (fold) => fold.unpricedModels.some((key) => isPriced(key));
|
|
3535
3588
|
/** 把一份(全量或增量)折叠结果登记进 durable ledger;内容无变化时不落盘。 */
|
|
3536
|
-
const recordLedger = (id, cwd, stamp, fold) => {
|
|
3589
|
+
const recordLedger = (id, cwd, stamp, fold, subOf) => {
|
|
3537
3590
|
if (options.ledger === void 0) return;
|
|
3538
3591
|
const entry = {
|
|
3539
3592
|
id,
|
|
3540
3593
|
...cwd === void 0 ? {} : { cwd },
|
|
3594
|
+
...subOf === void 0 ? {} : { subOf },
|
|
3541
3595
|
...stamp === null ? {} : { stamp },
|
|
3542
3596
|
foldVersion: 23,
|
|
3543
3597
|
fingerprint: foldFingerprint,
|
|
@@ -3545,7 +3599,7 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
3545
3599
|
fold: serializeFold(fold)
|
|
3546
3600
|
};
|
|
3547
3601
|
const row = ledger.get(id);
|
|
3548
|
-
if (row === void 0 || row.stamp !== entry.stamp || row.cwd !== entry.cwd || row.foldVersion !== entry.foldVersion || row.fingerprint !== entry.fingerprint || stamp === null && JSON.stringify(row.fold) !== JSON.stringify(entry.fold) || stamp !== null && foldNeedsReprice(row.fold)) {
|
|
3602
|
+
if (row === void 0 || row.stamp !== entry.stamp || row.cwd !== entry.cwd || row.subOf !== entry.subOf || row.foldVersion !== entry.foldVersion || row.fingerprint !== entry.fingerprint || stamp === null && JSON.stringify(row.fold) !== JSON.stringify(entry.fold) || stamp !== null && foldNeedsReprice(row.fold)) {
|
|
3549
3603
|
ledger.set(id, entry);
|
|
3550
3604
|
ledgerNeedsSave = true;
|
|
3551
3605
|
}
|
|
@@ -3637,12 +3691,14 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
3637
3691
|
}
|
|
3638
3692
|
try {
|
|
3639
3693
|
const cwd = meta.cwd;
|
|
3694
|
+
const subOf = subParentOf(meta);
|
|
3640
3695
|
const ledgerRow = ledger.get(id);
|
|
3641
3696
|
if (ledgerRow !== void 0 && ledgerRow.stamp !== void 0 && stamp !== null && ledgerRow.stamp === stamp && (ledgerRow.foldVersion ?? 1) === 23 && ledgerRow.fingerprint === foldFingerprint && !foldNeedsReprice(ledgerRow.fold)) {
|
|
3642
3697
|
const fold = deserializedFoldOf(ledgerRow.fold);
|
|
3643
3698
|
folds.push({
|
|
3644
3699
|
id,
|
|
3645
3700
|
...cwd === void 0 ? {} : { cwd },
|
|
3701
|
+
...subOf === void 0 ? {} : { subOf },
|
|
3646
3702
|
fold
|
|
3647
3703
|
});
|
|
3648
3704
|
included.add(id);
|
|
@@ -3655,6 +3711,7 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
3655
3711
|
folds.push({
|
|
3656
3712
|
id,
|
|
3657
3713
|
...meta.cwd === void 0 ? {} : { cwd: meta.cwd },
|
|
3714
|
+
...subOf === void 0 ? {} : { subOf },
|
|
3658
3715
|
fold: hit.fold
|
|
3659
3716
|
});
|
|
3660
3717
|
included.add(id);
|
|
@@ -3683,10 +3740,11 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
3683
3740
|
folds.push({
|
|
3684
3741
|
id,
|
|
3685
3742
|
...cwd === void 0 ? {} : { cwd },
|
|
3743
|
+
...subOf === void 0 ? {} : { subOf },
|
|
3686
3744
|
fold: previous.fold
|
|
3687
3745
|
});
|
|
3688
3746
|
included.add(id);
|
|
3689
|
-
recordLedger(id, cwd, stamp, previous.fold);
|
|
3747
|
+
recordLedger(id, cwd, stamp, previous.fold, subOf);
|
|
3690
3748
|
continue;
|
|
3691
3749
|
}
|
|
3692
3750
|
const { events, inheritedEventCount } = await persistence.readFrom(meta.id, sessionLogOffsetOf(0));
|
|
@@ -3712,10 +3770,11 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
3712
3770
|
folds.push({
|
|
3713
3771
|
id,
|
|
3714
3772
|
...cwd === void 0 ? {} : { cwd },
|
|
3773
|
+
...subOf === void 0 ? {} : { subOf },
|
|
3715
3774
|
fold
|
|
3716
3775
|
});
|
|
3717
3776
|
included.add(id);
|
|
3718
|
-
recordLedger(id, cwd, stamp, fold);
|
|
3777
|
+
recordLedger(id, cwd, stamp, fold, subOf);
|
|
3719
3778
|
} catch (error) {
|
|
3720
3779
|
skipped.push(id);
|
|
3721
3780
|
const format = isFormatUnsupportedError(error);
|
|
@@ -3743,6 +3802,7 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
3743
3802
|
folds.push({
|
|
3744
3803
|
id: entry.id,
|
|
3745
3804
|
...entry.cwd === void 0 ? {} : { cwd: entry.cwd },
|
|
3805
|
+
...entry.subOf === void 0 ? {} : { subOf: entry.subOf },
|
|
3746
3806
|
...stale ? { staleLedger: true } : {},
|
|
3747
3807
|
fold: deserializedFoldOf(entry.fold)
|
|
3748
3808
|
});
|
|
@@ -3779,7 +3839,7 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
3779
3839
|
const perfHourModel = /* @__PURE__ */ new Map();
|
|
3780
3840
|
const perfModelDigest = /* @__PURE__ */ new Map();
|
|
3781
3841
|
const perfHourDigest = /* @__PURE__ */ new Map();
|
|
3782
|
-
for (const { id: sessionId, cwd, fold, staleLedger } of folds) {
|
|
3842
|
+
for (const { id: sessionId, cwd, subOf, fold, staleLedger } of folds) {
|
|
3783
3843
|
mergeUsageInto(total, fold.total);
|
|
3784
3844
|
roles.userChars += fold.roles.userChars;
|
|
3785
3845
|
roles.toolChars += fold.roles.toolChars;
|
|
@@ -3858,12 +3918,14 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
3858
3918
|
id: sessionId,
|
|
3859
3919
|
...fold.title !== void 0 ? { title: fold.title } : {},
|
|
3860
3920
|
...cwd !== void 0 ? { cwd } : {},
|
|
3921
|
+
...subOf !== void 0 ? { parentId: subOf } : {},
|
|
3861
3922
|
...staleLedger === true ? { stale: true } : {},
|
|
3862
3923
|
calls: fold.total.calls,
|
|
3863
3924
|
cost: fold.total.cost,
|
|
3864
3925
|
lastActive: fold.lastActive
|
|
3865
3926
|
});
|
|
3866
3927
|
}
|
|
3928
|
+
foldSubagentFamilies(sessionRows);
|
|
3867
3929
|
sessionRows.sort((a, b) => b.cost - a.cost || b.lastActive - a.lastActive);
|
|
3868
3930
|
turnRows.sort((a, b) => b.startedAt - a.startedAt);
|
|
3869
3931
|
const workspaces = [...workspaceMap.values()].sort((a, b) => b.cost - a.cost || b.lastActive - a.lastActive);
|
package/lib/types/aggregate.d.ts
CHANGED
|
@@ -389,6 +389,17 @@ export interface SessionUsageRow {
|
|
|
389
389
|
title?: string;
|
|
390
390
|
/** 会话创建时的工作目录(项目路径);未知时缺失。 */
|
|
391
391
|
cwd?: string;
|
|
392
|
+
/**
|
|
393
|
+
* 直接父会话 id(仅子智能体会话携带):宿主 header 的 `origin: "subagent"`
|
|
394
|
+
* 会话经 parentSession 指向委派它的对话。fork/resume 的种子血缘
|
|
395
|
+
* (isSeeded)不满足子智能体门,不带本字段。旧宿主 header 无标记,
|
|
396
|
+
* 按顶层会话处理。
|
|
397
|
+
*/
|
|
398
|
+
parentId?: string;
|
|
399
|
+
/** 全部后代子会话的费用合计(人民币元,多级委派整链递归);无后代或后代全免费时缺失。 */
|
|
400
|
+
subCost?: number;
|
|
401
|
+
/** 全部后代子会话的调用数;无后代时缺失。 */
|
|
402
|
+
subCalls?: number;
|
|
392
403
|
calls: number;
|
|
393
404
|
cost: number;
|
|
394
405
|
/** 最后一个事件的时间戳(毫秒)。 */
|
|
@@ -396,6 +407,20 @@ export interface SessionUsageRow {
|
|
|
396
407
|
/** 数据来自旧算法折叠的持久账本行(日志已删/不可读,无法重算);UI 据此标注置信度。 */
|
|
397
408
|
stale?: boolean;
|
|
398
409
|
}
|
|
410
|
+
/**
|
|
411
|
+
* 从会话 header 提取子智能体归并标记(直接父会话 id):`origin: "subagent"`
|
|
412
|
+
* (宿主的产品分类)或 `delegationDepth > 0`(持久化委派深度)任一命中即视为
|
|
413
|
+
* 子会话。子会话但 header 无 parentSession(异常数据)返回 undefined——无法
|
|
414
|
+
* 归位就按顶层会话处理,保守不标。导出供测试。
|
|
415
|
+
*/
|
|
416
|
+
export declare function subParentOf(meta: SessionHeader): string | undefined;
|
|
417
|
+
/**
|
|
418
|
+
* 给会话行补后代合计(subCost/subCalls):按 parentId 建子索引,对每行递归
|
|
419
|
+
* 汇总全部后代子会话(多级委派整链计入根对话)。纯展示层归因——不改任何
|
|
420
|
+
* 总额桶(子会话费用本就在 total/byDay/byModel 里,行级只是拆出来给人看)。
|
|
421
|
+
* 环引用(异常数据)按 visited 跳过,不死循环。原地修改传入行。导出供测试。
|
|
422
|
+
*/
|
|
423
|
+
export declare function foldSubagentFamilies(rows: SessionUsageRow[]): void;
|
|
399
424
|
/** 每轮费用明细行:仪表盘「每轮费用」图的数据源。 */
|
|
400
425
|
export interface TurnUsageRow {
|
|
401
426
|
/** 会话 id(字符串形式):不同会话的轮次号相互独立,展示时需区分。 */
|
|
@@ -563,6 +588,12 @@ export interface SerializedSessionFold {
|
|
|
563
588
|
export interface UsageLedgerSession {
|
|
564
589
|
id: string;
|
|
565
590
|
cwd?: string;
|
|
591
|
+
/**
|
|
592
|
+
* 子智能体归并标记(直接父会话 id):仅宿主 header 带 `origin: "subagent"`
|
|
593
|
+
* 的会话行携带。日志已删、只剩账本行时仍能归位到父对话;缺失 = 顶层会话
|
|
594
|
+
* (含 fork/resume 血缘)。可选字段,旧账本行缺失按顶层处理,无需迁移。
|
|
595
|
+
*/
|
|
596
|
+
subOf?: string;
|
|
566
597
|
/** Stable log stamp (mtime + size) when the persistence backend exposes it. */
|
|
567
598
|
stamp?: string;
|
|
568
599
|
/**
|
|
@@ -178,6 +178,15 @@ interface SessionBillingRow {
|
|
|
178
178
|
id: string;
|
|
179
179
|
title?: string;
|
|
180
180
|
cwd?: string;
|
|
181
|
+
/**
|
|
182
|
+
* 直接父会话 id(仅子智能体会话携带):宿主把子智能体落成独立会话,
|
|
183
|
+
* header 的 origin: subagent + parentSession 指向委派它的对话。
|
|
184
|
+
*/
|
|
185
|
+
parentId?: string;
|
|
186
|
+
/** 全部后代子会话费用合计(服务端递归算好);无后代时缺失。 */
|
|
187
|
+
subCost?: number;
|
|
188
|
+
/** 全部后代子会话调用数;无后代时缺失。 */
|
|
189
|
+
subCalls?: number;
|
|
181
190
|
/** 数据来自旧算法折叠的持久账本行(原始日志已删,无法重算)。 */
|
|
182
191
|
stale?: boolean;
|
|
183
192
|
calls: number;
|
|
@@ -187,6 +196,8 @@ interface SessionBillingRow {
|
|
|
187
196
|
mergedCount?: number;
|
|
188
197
|
/** 合并组的段明细(展示层专用):一级行默认收起,展开后逐段显示。合并函数需 push,故非 readonly。 */
|
|
189
198
|
children?: SessionBillingRow[];
|
|
199
|
+
/** 挂到本组下的子智能体行(展示层专用):与段明细并列展开,带子智能体徽标。 */
|
|
200
|
+
subs?: SessionBillingRow[];
|
|
190
201
|
}
|
|
191
202
|
/** Usage stats structure from `.dsh-usage-stats.json`. */
|
|
192
203
|
export interface UsageStats {
|
|
@@ -18,6 +18,12 @@ export interface SessionExportRow {
|
|
|
18
18
|
id: string;
|
|
19
19
|
title?: string;
|
|
20
20
|
cwd?: string;
|
|
21
|
+
/** 直接父会话 id(仅子智能体会话携带);顶层会话缺失。 */
|
|
22
|
+
parentId?: string;
|
|
23
|
+
/** 后代子会话费用合计(人民币元);无后代时缺失。 */
|
|
24
|
+
subCost?: number;
|
|
25
|
+
/** 后代子会话调用数;无后代时缺失。 */
|
|
26
|
+
subCalls?: number;
|
|
21
27
|
calls: number;
|
|
22
28
|
cost: number;
|
|
23
29
|
lastActive: number;
|
|
@@ -26,7 +32,7 @@ export interface SessionExportRow {
|
|
|
26
32
|
export declare function dayRowsCsv(byDay: Record<string, DayExportRow>): string;
|
|
27
33
|
/** 按站点(中转站/直连/未知路由)CSV:站点,类别,调用,费用(元)。 */
|
|
28
34
|
export declare function siteRowsCsv(bySite: Record<string, DayExportRow>): string;
|
|
29
|
-
/** 按会话 CSV:会话 id,标题,项目,调用,费用(元),最后活跃(ISO)。 */
|
|
35
|
+
/** 按会话 CSV:会话 id,标题,项目,调用,费用(元),最后活跃(ISO),父会话,子会话调用,子会话费用(元)。 */
|
|
30
36
|
export declare function sessionRowsCsv(rows: readonly SessionExportRow[]): string;
|
|
31
37
|
/** 导出文件名:带日期范围(usage-2026-08-01_2026-08-22.csv);无日期时只带前缀。 */
|
|
32
38
|
export declare function exportFileName(prefix: string, ext: 'csv' | 'json', dates: readonly string[]): string;
|
|
@@ -22,6 +22,7 @@ export interface LiveStats {
|
|
|
22
22
|
bySession?: readonly {
|
|
23
23
|
id: string;
|
|
24
24
|
cost: number;
|
|
25
|
+
subCost?: number;
|
|
25
26
|
}[];
|
|
26
27
|
byTurn?: readonly {
|
|
27
28
|
sessionId: string;
|
|
@@ -40,13 +41,22 @@ export interface QuotaSlice {
|
|
|
40
41
|
}[];
|
|
41
42
|
}
|
|
42
43
|
/**
|
|
43
|
-
* 当前会话累计费用:bySession 里会话 id
|
|
44
|
-
*
|
|
44
|
+
* 当前会话累计费用:bySession 里会话 id 匹配的那行(含后代子智能体费用
|
|
45
|
+
* subCost——子智能体是宿主的独立会话,其消耗按父链并入本对话的口径);
|
|
46
|
+
* 缺省为 0。导出供测试:纯函数。
|
|
45
47
|
* @param stats - 薄统计切片。
|
|
46
48
|
* @param sessionId - 当前会话 id。
|
|
47
|
-
* @returns
|
|
49
|
+
* @returns 该会话累计费用(人民币元,含子智能体)。
|
|
48
50
|
*/
|
|
49
51
|
export declare function sessionCostOf(stats: LiveStats | null, sessionId: string | undefined): number;
|
|
52
|
+
/**
|
|
53
|
+
* 当前会话的后代子智能体费用(bySession 行的 subCost):供「含子」拆分展示,
|
|
54
|
+
* 让胶囊上的总额与本体会话费用对得上账。导出供测试:纯函数。
|
|
55
|
+
* @param stats - 薄统计切片。
|
|
56
|
+
* @param sessionId - 当前会话 id。
|
|
57
|
+
* @returns 后代子会话费用合计(人民币元);无则 0。
|
|
58
|
+
*/
|
|
59
|
+
export declare function sessionSubCostOf(stats: LiveStats | null, sessionId: string | undefined): number;
|
|
50
60
|
/**
|
|
51
61
|
* 当前轮费用:byTurn 里该会话最新一轮的 cost;缺省为 0。
|
|
52
62
|
* byTurn 服务端按起始时间倒序下发,但求 max(turn) 更稳健(不依赖顺序)。
|
|
@@ -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' | 'kpiRange' | 'avgRangeToday' | 'avgRange7d' | 'avgRangeWeek' | 'avgRangeMonth' | 'avgRangeAll' | 'trend' | 'trend7d' | 'trend30d' | 'trendMetric' | 'trendMetricCost' | 'trendMetricTokens' | 'pricingSearch' | 'bandPinHint' | 'trendEmpty' | 'trendTotal' | 'roundsUnit' | 'healthModelsLive' | 'healthVendorsDown' | 'healthVendorsUnavailable' | 'budget' | 'budgetRemain' | 'budgetAmount' | 'budgetSummary' | 'sessions' | 'sessionTitle' | 'lastActive' | 'sessionOverflow' | 'budgetTierBody' | 'models' | 'providerBilling' | 'channelUnknown' | 'directTag' | 'relayTag' | 'unknownTag' | 'unknownChannelHint' | 'planCountUnit' | 'actual' | 'pricing' | 'input' | 'output' | 'cacheHit' | 'peak' | 'offPeak' | 'flat' | 'band' | 'close' | 'footer' | 'footerCredit' | 'lastUpdated' | 'noData' | 'todayRate' | 'rateLive' | 'rateBuiltin' | 'pricingSyncedAt' | 'pricingSyncNow' | 'pricingSyncing' | 'promoBadge' | 'promoUntil' | 'promoOpenEnded' | 'pricingTip' | 'pricingUnit' | 'pricingNotes' | 'ubPeak' | 'ubOff' | 'ubStd' | 'peakBand' | 'pricingSource' | 'noteCache' | 'noteBand' | 'noteSource' | 'balance' | 'recharge' | 'rechargeHint' | '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' | 'floatPrimaryToday' | 'floatPrimaryWeek' | 'floatPrimaryMonth' | 'floatNoTargets' | 'floatNoTargetsHint' | 'cardDisplay' | 'cardDisplayHint' | 'cardMetric' | 'cardMetricMoney' | 'cardMetricTokens' | 'cardSpan' | 'cardSpanDay' | 'cardSpanWeek' | 'cardSpanMonth' | 'triggerMonthTokens' | 'triggerTodayTokens' | 'triggerWeekTokens' | 'subscriptionsStale' | 'staleLedgerNotice' | 'unreadableNotice' | 'unreadableFormatNotice' | 'unreadableNoLedgerNotice' | 'tokenCacheWrite' | 'toolRank' | 'toolName' | 'userPrices' | 'userPricesHint' | 'userPriceSave' | 'userPriceModel' | 'userPriceSource' | 'userPriceSourceHint' | 'userPriceOffPeak' | 'userPriceNormal' | 'userPriceCurrency' | 'userPriceAdd' | 'userPriceRemoveSelected' | 'userPriceSelect' | 'sessionStaleBadge' | 'sessionUntitled' | 'heatmapLess' | 'heatmapMore' | 'currency' | 'currencyCny' | 'currencyUsd' | 'currencyEur' | 'language' | 'heatmap' | 'rounds' | 'roundsHint' | 'anomaly' | 'model' | 'thModel' | 'thInputMiss' | 'thInputHit' | 'costAbbr' | 'tabOverview' | 'tabTrends' | 'tabProviders' | 'tabPricing' | 'tabSettings' | 'budgetHint' | 'peakAlertHint' | 'peakAlertDescPeak' | 'peakAlertDescOff' | 'peakAlertDescPeakZhipu' | 'peakAlertDescOffZhipu' | 'export' | 'exportCsvDay' | 'exportCsvSession' | 'exportJson' | 'peakShare' | 'peakSharePerCall' | 'offPeakSavings' | 'perfMax' | 'weekCost' | 'roleCost' | 'roleUser' | 'roleAssistant' | 'roleTool' | 'roleHint' | 'tierPeak' | 'tierOff' | 'tierToPeak' | 'tierToOff' | 'tierAlertEnterPeak' | 'tierAlertEnterOff' | 'tierAlertEnterPeakZhipu' | 'tierAlertEnterOffZhipu' | 'peakAlertTitlePeak' | 'peakAlertTitleOff' | 'peakAlert' | 'peakAlertLeadMin' | 'peakAlertPos' | 'peakAlertMode' | 'peakAlertPosCorner' | 'peakAlertPosCenter' | 'peakAlertModePeak' | 'peakAlertModeOff' | 'peakAlertModeBoth' | 'peakAlertWebNotify' | 'peakAlertPreview' | 'planTypeCode' | 'planTypeToken' | 'subscriptionFeePerMonth' | 'triggerToday' | 'triggerMonth' | 'subscriptionTag' | 'cellEstimateHint' | 'free' | 'perfSamples' | 'perfTtft' | 'perfP50' | 'perfP90' | 'perfTps' | 'perfLatency' | 'perfEstimated' | 'perfEmpty' | 'perfTpsUnit' | 'perfTitle' | 'perfHint' | 'perfAll' | 'perfChartEmpty' | 'heatmapYear' | 'heatmapHalf' | 'heatmapMonth' | 'metricCost' | 'metricTokens' | 'heatmapTotal' | 'activeDays' | 'streakDays' | 'subscriptionAutoDetect' | 'pluginAuthor' | 'pluginRepository' | 'pluginNpm' | 'pluginLicense' | 'tabToken' | 'tokenExport' | 'tokenExportCsv' | 'tokenReasoningShare' | 'tokenReasoningShort' | 'tokenIo' | 'tokenPeak' | 'densityLabel' | 'densityHint' | 'densityCompact' | 'densityDefault' | 'densityComfortable' | 'motionLabel' | 'motionHint' | 'motionOff' | 'motionSubtle' | 'motionRich' | 'settingsNavBudget' | 'settingsNavAlert' | 'settingsNavDisplay' | 'settingsNavAdvanced' | 'settingsNavAbout' | 'settingsSectionDisplay' | 'emptyHint' | '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' | 'expandAll' | 'collapseAll' | 'todayOnly' | 'todayNoConsumption';
|
|
2
|
+
export type UsageBillingKey = 'title' | 'cost' | 'todayCost' | 'monthCost' | 'yearCost' | 'monthProjected' | 'liveTurn' | 'liveSession' | 'liveSessionSub' | 'calls' | 'cacheHitRate' | 'tokens' | 'inputTokens' | 'outputTokens' | 'avgCost' | 'kpiRange' | 'avgRangeToday' | 'avgRange7d' | 'avgRangeWeek' | 'avgRangeMonth' | 'avgRangeAll' | 'trend' | 'trend7d' | 'trend30d' | 'trendMetric' | 'trendMetricCost' | 'trendMetricTokens' | 'pricingSearch' | 'bandPinHint' | 'trendEmpty' | 'trendTotal' | 'roundsUnit' | 'healthModelsLive' | 'healthVendorsDown' | 'healthVendorsUnavailable' | 'budget' | 'budgetRemain' | 'budgetAmount' | 'budgetSummary' | 'sessions' | 'sessionTitle' | 'lastActive' | 'sessionOverflow' | 'budgetTierBody' | 'models' | 'providerBilling' | 'channelUnknown' | 'directTag' | 'relayTag' | 'unknownTag' | 'unknownChannelHint' | 'planCountUnit' | 'actual' | 'pricing' | 'input' | 'output' | 'cacheHit' | 'peak' | 'offPeak' | 'flat' | 'band' | 'close' | 'footer' | 'footerCredit' | 'lastUpdated' | 'noData' | 'todayRate' | 'rateLive' | 'rateBuiltin' | 'pricingSyncedAt' | 'pricingSyncNow' | 'pricingSyncing' | 'promoBadge' | 'promoUntil' | 'promoOpenEnded' | 'pricingTip' | 'pricingUnit' | 'pricingNotes' | 'ubPeak' | 'ubOff' | 'ubStd' | 'peakBand' | 'pricingSource' | 'noteCache' | 'noteBand' | 'noteSource' | 'balance' | 'recharge' | 'rechargeHint' | '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' | 'floatPrimaryToday' | 'floatPrimaryWeek' | 'floatPrimaryMonth' | 'floatNoTargets' | 'floatNoTargetsHint' | 'cardDisplay' | 'cardDisplayHint' | 'cardMetric' | 'cardMetricMoney' | 'cardMetricTokens' | 'cardSpan' | 'cardSpanDay' | 'cardSpanWeek' | 'cardSpanMonth' | 'cardDeltaBadge' | 'cardDeltaShow' | 'cardDeltaHide' | 'triggerMonthTokens' | 'triggerTodayTokens' | 'triggerWeekTokens' | 'subscriptionsStale' | 'staleLedgerNotice' | 'unreadableNotice' | 'unreadableFormatNotice' | 'unreadableNoLedgerNotice' | 'tokenCacheWrite' | 'toolRank' | 'toolName' | 'userPrices' | 'userPricesHint' | 'userPriceSave' | 'userPriceModel' | 'userPriceSource' | 'userPriceSourceHint' | 'userPriceOffPeak' | 'userPriceNormal' | 'userPriceCurrency' | 'userPriceAdd' | 'userPriceRemoveSelected' | 'userPriceSelect' | 'sessionStaleBadge' | 'sessionUntitled' | 'sessionSubCost' | 'sessionSubCalls' | 'sessionSubRow' | 'heatmapLess' | 'heatmapMore' | 'currency' | 'currencyCny' | 'currencyUsd' | 'currencyEur' | 'language' | 'heatmap' | 'rounds' | 'roundsHint' | 'anomaly' | 'model' | 'thModel' | 'thInputMiss' | 'thInputHit' | 'costAbbr' | 'tabOverview' | 'tabTrends' | 'tabProviders' | 'tabPricing' | 'tabSettings' | 'budgetHint' | 'peakAlertHint' | 'peakAlertDescPeak' | 'peakAlertDescOff' | 'peakAlertDescPeakZhipu' | 'peakAlertDescOffZhipu' | 'export' | 'exportCsvDay' | 'exportCsvSession' | 'exportJson' | 'peakShare' | 'peakSharePerCall' | 'offPeakSavings' | 'perfMax' | 'weekCost' | 'roleCost' | 'roleUser' | 'roleAssistant' | 'roleTool' | 'roleHint' | 'tierPeak' | 'tierOff' | 'tierToPeak' | 'tierToOff' | 'tierAlertEnterPeak' | 'tierAlertEnterOff' | 'tierAlertEnterPeakZhipu' | 'tierAlertEnterOffZhipu' | 'peakAlertTitlePeak' | 'peakAlertTitleOff' | 'peakAlert' | 'peakAlertLeadMin' | 'peakAlertPos' | 'peakAlertMode' | 'peakAlertPosCorner' | 'peakAlertPosCenter' | 'peakAlertModePeak' | 'peakAlertModeOff' | 'peakAlertModeBoth' | 'peakAlertWebNotify' | 'peakAlertPreview' | 'planTypeCode' | 'planTypeToken' | 'subscriptionFeePerMonth' | 'triggerToday' | 'triggerMonth' | 'subscriptionTag' | 'cellEstimateHint' | 'free' | 'perfSamples' | 'perfTtft' | 'perfP50' | 'perfP90' | 'perfTps' | 'perfLatency' | 'perfEstimated' | 'perfEmpty' | 'perfTpsUnit' | 'perfTitle' | 'perfHint' | 'perfAll' | 'perfChartEmpty' | 'heatmapYear' | 'heatmapHalf' | 'heatmapMonth' | 'metricCost' | 'metricTokens' | 'heatmapTotal' | 'activeDays' | 'streakDays' | 'subscriptionAutoDetect' | 'pluginAuthor' | 'pluginRepository' | 'pluginNpm' | 'pluginLicense' | 'tabToken' | 'tokenExport' | 'tokenExportCsv' | 'tokenReasoningShare' | 'tokenReasoningShort' | 'tokenIo' | 'tokenPeak' | 'densityLabel' | 'densityHint' | 'densityCompact' | 'densityDefault' | 'densityComfortable' | 'motionLabel' | 'motionHint' | 'motionOff' | 'motionSubtle' | 'motionRich' | 'settingsNavBudget' | 'settingsNavAlert' | 'settingsNavDisplay' | 'settingsNavAdvanced' | 'settingsNavAbout' | 'settingsSectionDisplay' | 'emptyHint' | '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' | 'expandAll' | 'collapseAll' | 'todayOnly' | 'todayNoConsumption';
|
|
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>;
|
|
@@ -54,8 +54,10 @@ export interface BillingCardPrefs {
|
|
|
54
54
|
metric: BillingCardMetric;
|
|
55
55
|
/** 主数字统计范围:今日 / 本周 / 本月(默认今日)。 */
|
|
56
56
|
span: BillingCardSpan;
|
|
57
|
+
/** 是否显示「今日环比」涨跌徽章(默认显示;issue #93:部分用户觉得红色横条太醒目)。 */
|
|
58
|
+
showDelta: boolean;
|
|
57
59
|
}
|
|
58
|
-
/** 默认计费卡偏好:花费金额 +
|
|
60
|
+
/** 默认计费卡偏好:花费金额 + 今日口径 + 显示环比徽章(保持 v1.5.0 行为)。 */
|
|
59
61
|
export declare const DEFAULT_BILLING_CARD_PREFS: BillingCardPrefs;
|
|
60
62
|
/** localStorage key(与 budget store 的 `dsh.ui-usage-billing.*` 命名空间一致)。 */
|
|
61
63
|
export declare const BILLING_CARD_STORAGE_KEY = "dsh.ui-usage-billing.card";
|
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.5.
|
|
4
|
+
"version": "1.5.1",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
7
7
|
"deepseek",
|
|
@@ -77,7 +77,8 @@
|
|
|
77
77
|
"0.2.0-rc.2": "compatible",
|
|
78
78
|
"0.2.1-alpha.1": "compatible",
|
|
79
79
|
"0.2.1-alpha.2": "compatible",
|
|
80
|
-
"0.2.1-alpha.3": "compatible"
|
|
80
|
+
"0.2.1-alpha.3": "compatible",
|
|
81
|
+
"0.2.1-rc.2": "compatible"
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
},
|
|
@@ -122,35 +123,36 @@
|
|
|
122
123
|
"@deepseek-ai/cordis": "*",
|
|
123
124
|
"@deepseek-ai/cordis-plugin-include": "^1.0.7",
|
|
124
125
|
"@deepseek-ai/cordis-plugin-loader": "^1.0.5",
|
|
125
|
-
"@deepseek-ai/dsh-api-gateway": "0.1
|
|
126
|
-
"@deepseek-ai/dsh-api-remotes": "0.1
|
|
127
|
-
"@deepseek-ai/dsh-api-session-controller": "0.1
|
|
128
|
-
"@deepseek-ai/dsh-atomic-write": "0.1
|
|
129
|
-
"@deepseek-ai/dsh-agent": "0.1
|
|
130
|
-
"@deepseek-ai/dsh-client-locale": "0.1
|
|
131
|
-
"@deepseek-ai/dsh-client-store": "0.1
|
|
132
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.1
|
|
133
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.1
|
|
134
|
-
"@deepseek-ai/dsh-client-ui-renderer": "0.1
|
|
135
|
-
"@deepseek-ai/dsh-client-ui-sidebar": "0.1
|
|
136
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.1
|
|
137
|
-
"@deepseek-ai/dsh-credentials": "0.1
|
|
138
|
-
"@deepseek-ai/dsh-host-webserver": "0.1
|
|
139
|
-
"@deepseek-ai/dsh-home-paths": "0.1
|
|
140
|
-
"@deepseek-ai/dsh-invariants": "0.
|
|
141
|
-
"@deepseek-ai/dsh-
|
|
142
|
-
"@deepseek-ai/dsh-
|
|
143
|
-
"@deepseek-ai/dsh-
|
|
144
|
-
"@deepseek-ai/dsh-sandbox
|
|
145
|
-
"@deepseek-ai/dsh-
|
|
146
|
-
"@deepseek-ai/dsh-
|
|
147
|
-
"@deepseek-ai/dsh-session
|
|
148
|
-
"@deepseek-ai/dsh-
|
|
149
|
-
"@deepseek-ai/dsh-
|
|
150
|
-
"@deepseek-ai/dsh-
|
|
151
|
-
"@deepseek-ai/dsh-
|
|
152
|
-
"@deepseek-ai/dsh-
|
|
153
|
-
"@deepseek-ai/dsh-
|
|
126
|
+
"@deepseek-ai/dsh-api-gateway": "0.2.1-rc.2",
|
|
127
|
+
"@deepseek-ai/dsh-api-remotes": "0.2.1-rc.2",
|
|
128
|
+
"@deepseek-ai/dsh-api-session-controller": "0.2.1-rc.2",
|
|
129
|
+
"@deepseek-ai/dsh-atomic-write": "0.2.1-rc.2",
|
|
130
|
+
"@deepseek-ai/dsh-agent": "0.2.1-rc.2",
|
|
131
|
+
"@deepseek-ai/dsh-client-locale": "0.2.1-rc.2",
|
|
132
|
+
"@deepseek-ai/dsh-client-store": "0.2.1-rc.2",
|
|
133
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.2.1-rc.2",
|
|
134
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.2.1-rc.2",
|
|
135
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.1-rc.2",
|
|
136
|
+
"@deepseek-ai/dsh-client-ui-sidebar": "0.2.1-rc.2",
|
|
137
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.1-rc.2",
|
|
138
|
+
"@deepseek-ai/dsh-credentials": "0.2.1-rc.2",
|
|
139
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.1-rc.2",
|
|
140
|
+
"@deepseek-ai/dsh-home-paths": "0.2.1-rc.2",
|
|
141
|
+
"@deepseek-ai/dsh-invariants": "0.2.0-rc.2",
|
|
142
|
+
"@deepseek-ai/dsh-util-code-language": "0.2.1-rc.2",
|
|
143
|
+
"@deepseek-ai/dsh-llm": "0.2.1-rc.2",
|
|
144
|
+
"@deepseek-ai/dsh-ptc-runtime": "0.2.1-rc.2",
|
|
145
|
+
"@deepseek-ai/dsh-sandbox": "0.2.1-rc.2",
|
|
146
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.2.1-rc.2",
|
|
147
|
+
"@deepseek-ai/dsh-scope": "0.2.1-rc.2",
|
|
148
|
+
"@deepseek-ai/dsh-session": "0.2.1-rc.2",
|
|
149
|
+
"@deepseek-ai/dsh-session-persistence": "0.2.1-rc.2",
|
|
150
|
+
"@deepseek-ai/dsh-settings": "0.2.1-rc.2",
|
|
151
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.1-rc.2",
|
|
152
|
+
"@deepseek-ai/dsh-tools": "0.2.1-rc.2",
|
|
153
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.1-rc.2",
|
|
154
|
+
"@deepseek-ai/dsh-user-approval": "0.2.1-rc.2",
|
|
155
|
+
"@deepseek-ai/dsh-util-workspace-path": "0.2.1-rc.2",
|
|
154
156
|
"@deepseek-ai/schemastery": "^3.18.4",
|
|
155
157
|
"@shikijs/langs": "^4.3.1",
|
|
156
158
|
"@testing-library/dom": "^10.4.1",
|