@kenz1117/dsh-ui-usage-billing 1.1.13 → 1.2.0
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 +42 -24
- package/README.md +37 -32
- package/lib/client.js +5 -5
- package/lib/index.js +558 -61
- package/lib/types/aggregate.d.ts +81 -28
- package/lib/types/client/PerfPanel.d.ts +10 -8
- package/lib/types/client/TokenPanel.d.ts +55 -3
- package/lib/types/client/apply.d.ts +10 -3
- package/lib/types/client/budget-store.d.ts +1 -1
- package/lib/types/client/completion-notify.d.ts +2 -2
- package/lib/types/client/live-cost.d.ts +19 -9
- package/lib/types/client/locales.d.ts +1 -1
- package/lib/types/client/pricing.d.ts +60 -8
- package/lib/types/client/provider-display.d.ts +7 -0
- package/lib/types/client/usage-billing-settings.d.ts +42 -0
- package/lib/types/index.d.ts +24 -1
- package/lib/types/subscriptions.d.ts +2 -0
- package/lib/types/tc3.d.ts +60 -0
- package/package.json +46 -24
|
@@ -73,6 +73,28 @@ export declare const SITE_LIST_STORAGE_KEY = "dsh.ui-usage-billing.sites";
|
|
|
73
73
|
export declare function loadSiteListPrefs(): SiteListPrefs;
|
|
74
74
|
/** 写入站点列表偏好。失败静默(展示偏好非关键)。 */
|
|
75
75
|
export declare function saveSiteListPrefs(prefs: SiteListPrefs): void;
|
|
76
|
+
/**
|
|
77
|
+
* 即时代费条(平价消耗胶囊,composer dock 的 LiveCostBar)的显示偏好。
|
|
78
|
+
* 纯 client 偏好,存 localStorage(不依赖 node 半区接口/设置 schema);
|
|
79
|
+
* 设置 Tab 与 LiveCostBar 分属两个 React 树,跨树同步走 localStorage +
|
|
80
|
+
* `LIVE_COST_BAR_PREF_EVENT` CustomEvent(同文档即时生效,跨标签页靠 storage 事件)。
|
|
81
|
+
*/
|
|
82
|
+
export interface LiveCostBarPrefs {
|
|
83
|
+
/** 是否显示输入框下方的即时代费条胶囊(默认 true:保持历史行为)。 */
|
|
84
|
+
show: boolean;
|
|
85
|
+
/** 胶囊位置:below = 输入框下方(默认);above = 输入框上方;toolbar = 工具行模型选择前的内联 chip。 */
|
|
86
|
+
position: 'below' | 'above' | 'toolbar';
|
|
87
|
+
}
|
|
88
|
+
/** 默认即时代费条偏好:显示在输入框下方(升级用户零感知)。 */
|
|
89
|
+
export declare const DEFAULT_LIVE_COST_BAR_PREFS: LiveCostBarPrefs;
|
|
90
|
+
/** localStorage key(与其他 `dsh.ui-usage-billing.*` 偏好同命名空间)。 */
|
|
91
|
+
export declare const LIVE_COST_BAR_STORAGE_KEY = "dsh.ui-usage-billing.livecost";
|
|
92
|
+
/** 设置 Tab 切换后派发的 CustomEvent 名(LiveCostBar 监听它即时显隐)。 */
|
|
93
|
+
export declare const LIVE_COST_BAR_PREF_EVENT = "dsh.ui-usage-billing.livecost-pref";
|
|
94
|
+
/** 读取即时代费条偏好(含损坏/缺失回退到默认)。仅在浏览器半区调用。 */
|
|
95
|
+
export declare function loadLiveCostBarPrefs(): LiveCostBarPrefs;
|
|
96
|
+
/** 写入即时代费条偏好。失败静默(展示偏好非关键)。 */
|
|
97
|
+
export declare function saveLiveCostBarPrefs(prefs: LiveCostBarPrefs): void;
|
|
76
98
|
/** 用户自定义单价(与 client/pricing.ts 的 `UserPriceEntry` 同形;type import,无运行时依赖)。 */
|
|
77
99
|
export type StoredUserPrice = UserPriceEntry;
|
|
78
100
|
/** 自定义价表:模型(+可选来源)→ 单价,条目列表(支持同名模型绑定不同中转站 origin)。 */
|
|
@@ -87,4 +109,24 @@ export declare const USER_PRICES_STORAGE_KEY = "dsh.ui-usage-billing.prices";
|
|
|
87
109
|
export declare function loadUserPrices(): UserPriceMap;
|
|
88
110
|
/** 写入用户自定义价。失败静默(展示偏好非关键)。 */
|
|
89
111
|
export declare function saveUserPrices(prices: UserPriceMap): void;
|
|
112
|
+
/** 性能曲线的指标视角。 */
|
|
113
|
+
export type PerfMetric = 'ttft' | 'tps';
|
|
114
|
+
/**
|
|
115
|
+
* 性能面板的视图偏好:当前指标 tab 与点亮的模型曲线集合。
|
|
116
|
+
* 纯 client 偏好,存 localStorage(不依赖 node 半区接口/设置 schema)。
|
|
117
|
+
*/
|
|
118
|
+
export interface PerfViewPrefs {
|
|
119
|
+
/** 当前指标:首字延时(ms)/ 生成速度(tok/s)。 */
|
|
120
|
+
metric: PerfMetric;
|
|
121
|
+
/** 点亮的模型键列表;缺省 = 按样本数前 5(用户未碰过图例时跟随默认)。 */
|
|
122
|
+
models?: string[];
|
|
123
|
+
}
|
|
124
|
+
/** 默认性能视图偏好:首字延时 tab;模型集合跟随默认(前 5)。 */
|
|
125
|
+
export declare const DEFAULT_PERF_VIEW_PREFS: PerfViewPrefs;
|
|
126
|
+
/** localStorage key(与其他 `dsh.ui-usage-billing.*` 偏好同命名空间)。 */
|
|
127
|
+
export declare const PERF_VIEW_STORAGE_KEY = "dsh.ui-usage-billing.perf";
|
|
128
|
+
/** 读取性能视图偏好(含损坏/缺失回退到默认)。仅在浏览器半区调用。 */
|
|
129
|
+
export declare function loadPerfViewPrefs(): PerfViewPrefs;
|
|
130
|
+
/** 写入性能视图偏好。失败静默(展示偏好非关键)。 */
|
|
131
|
+
export declare function savePerfViewPrefs(prefs: PerfViewPrefs): void;
|
|
90
132
|
//# sourceMappingURL=usage-billing-settings.d.ts.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
|
16
16
|
import type { Context } from '@deepseek-ai/cordis';
|
|
17
17
|
import type { CredentialProvider } from '@deepseek-ai/dsh-credentials';
|
|
18
18
|
import type { SettingsProvider } from '@deepseek-ai/dsh-settings';
|
|
19
|
-
import { type UsageLedgerStore } from './aggregate.ts';
|
|
19
|
+
import { type UsageLedgerStore, type UsagePersistence } from './aggregate.ts';
|
|
20
20
|
import type { CustomBalanceConfig, DeclaredEndpointConfig, SubscriptionPlanConfig } from './pricing-shared.ts';
|
|
21
21
|
import { type IdentifiedSubscriptionPlan, type SubscriptionKeys } from './subscriptions.ts';
|
|
22
22
|
/**
|
|
@@ -68,6 +68,18 @@ export interface UsageBillingConfig {
|
|
|
68
68
|
* 计费但本地日志无 usage,按次估值计入今日/本月费用;默认 0.02 元/次,设 0 关闭。
|
|
69
69
|
*/
|
|
70
70
|
searchCallEstimateCny?: number;
|
|
71
|
+
/**
|
|
72
|
+
* 历史路由别名(旧 provider 路由名 → 当前路由名):改过名/删除过的路由,其
|
|
73
|
+
* 历史用量原会落「未知路由」桶且站点/订阅/官方判定全部失效;配置别名后按
|
|
74
|
+
* 目标路由归位。例:`{ "deepseek-official": "tencent", "tencent-cloud": "tencent" }`。
|
|
75
|
+
*/
|
|
76
|
+
routeAliases?: Record<string, string>;
|
|
77
|
+
/**
|
|
78
|
+
* 用户自定义模型别名(真实日志 model id → 计费目录键):目录外的新模型无需
|
|
79
|
+
* 等发版,配置一条别名即完成识别与计价(值必须是 MODEL_CATALOG 的既有 key,
|
|
80
|
+
* 如 `{ "hy4-preview": "hunyuan" }`)。聚合折叠与客户端渲染共用同一映射。
|
|
81
|
+
*/
|
|
82
|
+
modelKeyAliases?: Record<string, string>;
|
|
71
83
|
}
|
|
72
84
|
/**
|
|
73
85
|
* Create the atomic file-backed durable-ledger store. The previous complete file
|
|
@@ -110,6 +122,17 @@ export declare function resolveSubscriptionKeys(settings: SettingsProvider, cred
|
|
|
110
122
|
keys: SubscriptionKeys;
|
|
111
123
|
identified: IdentifiedSubscriptionPlan[];
|
|
112
124
|
}>;
|
|
125
|
+
/**
|
|
126
|
+
* 宿主 persistence 形状适配。宿主 0.1.3 起 SessionPersistence 改为
|
|
127
|
+
* SessionHandle 模型(open(id,'read') 后经 handle.read(offset) 读,fork 边界
|
|
128
|
+
* 挂在 handle.inheritedEventCount,list 返回 {header, revision} 快照行,
|
|
129
|
+
* 0.1.2 的 readFrom/locate 消失)。这里按结构探测把两种宿主形状都收敛为
|
|
130
|
+
* 聚合层期望的 0.1.2 面貌:0.1.2 直接带 readFrom 的原样直通;0.1.3 的
|
|
131
|
+
* 读取转为 open → handle.read,revision 令牌经 stampOf 暴露给增量缓存。
|
|
132
|
+
* 候选时刻的运行时对象是宿主注入的外部形状,结构断言即 durable 收窄点。
|
|
133
|
+
* 导出供测试:纯函数(不触 ctx)。
|
|
134
|
+
*/
|
|
135
|
+
export declare function adaptSessionPersistence(raw: unknown): UsagePersistence;
|
|
113
136
|
/**
|
|
114
137
|
* Host plugin body: serve real aggregated usage to the browser dashboard.
|
|
115
138
|
* @param ctx - host context carrying webServer and sessionPersistence.
|
|
@@ -24,6 +24,8 @@ export interface SubscriptionKeys {
|
|
|
24
24
|
minmaxApiKey: string;
|
|
25
25
|
/** OpenRouter API key(credits 已用%)。 */
|
|
26
26
|
openrouterApiKey: string;
|
|
27
|
+
/** 腾讯云云 API 密钥对(`<SecretId>:<SecretKey>`,管控面用,非 TokenHub 推理 key)。 */
|
|
28
|
+
tencentCloudApi: string;
|
|
27
29
|
/** Z.ai 区域(global / bigmodel-cn)。 */
|
|
28
30
|
zaiRegion: 'global' | 'bigmodel-cn';
|
|
29
31
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tencent Cloud TokenHub control-plane access (cloud API 3.0, TC3-HMAC-SHA256).
|
|
3
|
+
*
|
|
4
|
+
* Shared by two surfaces that read the same Token Plan:
|
|
5
|
+
* - `balance.ts` — the balance row (absolute remaining quota);
|
|
6
|
+
* - `subscriptions.ts` — the subscription card (monthly window + plan name).
|
|
7
|
+
*
|
|
8
|
+
* Credentials are a cloud API key pair (`<SecretId>:<SecretKey>`), NOT the
|
|
9
|
+
* TokenHub inference key. Field names on the control plane are not fully
|
|
10
|
+
* stable, so parsing stays defensive (semantic-key scanning).
|
|
11
|
+
*/
|
|
12
|
+
/** TokenHub 管控面 API 端点(cloud.tencent.cn/document/api/1823/132270)。 */
|
|
13
|
+
export declare const TOKENHUB_HOST = "tokenhub.tencentcloudapi.com";
|
|
14
|
+
/** 管控面调用超时(毫秒):余额与订阅面板共用同一预算。 */
|
|
15
|
+
export declare const TOKENHUB_TIMEOUT_MS = 8000;
|
|
16
|
+
/** 腾讯云凭据引用值格式:`<SecretId>:<SecretKey>`(分隔符取首个冒号)。 */
|
|
17
|
+
export declare function parseTencentCredential(value: string): {
|
|
18
|
+
secretId: string;
|
|
19
|
+
secretKey: string;
|
|
20
|
+
} | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* 构造云 API 3.0 TC3-HMAC-SHA256 签名(官方签名方法 v3)。导出供测试:纯函数,
|
|
23
|
+
* 输入确定则签名确定。Action 不参与签名——它走 `X-TC-Action` 请求头。
|
|
24
|
+
* @param secretId - 云 API SecretId。
|
|
25
|
+
* @param secretKey - 云 API SecretKey。
|
|
26
|
+
* @param payload - 已序列化的请求体(含 Action/Version/Region 公共参数)。
|
|
27
|
+
* @param timestamp - 签名时间戳(秒)。
|
|
28
|
+
* @returns Authorization 头的值。
|
|
29
|
+
*/
|
|
30
|
+
export declare function tc3Authorization(secretId: string, secretKey: string, payload: string, timestamp: number): string;
|
|
31
|
+
/**
|
|
32
|
+
* 调用一次 TokenHub 管控面接口:TC3 签名 + 超时保护,返回响应 JSON 的 `Response`。
|
|
33
|
+
* 业务错误(Response.Error)与 HTTP 层错误都带 `code` 抛出,调用方按
|
|
34
|
+
* unauthorized / unreachable / invalid 归类。
|
|
35
|
+
*/
|
|
36
|
+
export declare function callTokenHub(secretId: string, secretKey: string, action: string, params: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
37
|
+
/** 数字归一化:上游可能给字符串数字;非有限数返回 undefined。 */
|
|
38
|
+
export declare function toNumber(value: unknown): number | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* 在套餐余量对象里防御性提取「剩余额度」:官方 SubPackageBalance/PackageInfo
|
|
41
|
+
* 的字段名未稳定公开(issue #18 调研期),按语义键名扫描——命中 remaining /
|
|
42
|
+
* balance / left 语义键直接用;命中 total 与 used 则相减推导。数字一律经
|
|
43
|
+
* {@link toNumber} 归一化(上游可能给字符串)。
|
|
44
|
+
* 导出供测试:纯函数。
|
|
45
|
+
* @param source - 套餐详情里的余量对象(PackageInfo / SubPackageBalance 等)。
|
|
46
|
+
* @returns 剩余额度(上游单位,通常为 token 数或元);提取不到返回 undefined。
|
|
47
|
+
*/
|
|
48
|
+
export declare function pickRemainingQuota(source: unknown): number | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* 防御性提取「总额度」:语义键 total / limit / quota。与
|
|
51
|
+
* {@link pickRemainingQuota} 配对使用——两者都能取到时订阅卡才能算出
|
|
52
|
+
* 已用百分比窗口;只有剩余值时窗口保持为空(绝不猜总额度)。
|
|
53
|
+
* 注意排除键名:`RemainingQuota` / `UsedQuota` 这类键同样含 quota 子串,
|
|
54
|
+
* 必须先剔除剩余 / 已用语义,否则会把剩余值误当总额度(有单测守卫)。
|
|
55
|
+
* @param source - 套餐详情里的额度对象(PackageInfo / SubPackageBalance 等)。
|
|
56
|
+
*/
|
|
57
|
+
export declare function pickTotalQuota(source: unknown): number | undefined;
|
|
58
|
+
/** 套餐列表里提取第一个启用套餐的 TeamId:集合字段名做候选兼容。 */
|
|
59
|
+
export declare function firstEnabledTeamId(inner: Record<string, unknown>): string | undefined;
|
|
60
|
+
//# sourceMappingURL=tc3.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
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.
|
|
4
|
+
"version": "1.2.0",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"deepseek-harness",
|
|
7
|
+
"deepseek",
|
|
8
|
+
"dsh",
|
|
9
|
+
"dsh-plugin",
|
|
10
|
+
"billing",
|
|
11
|
+
"cost-tracking",
|
|
12
|
+
"token-usage",
|
|
13
|
+
"usage-stats",
|
|
14
|
+
"llm",
|
|
15
|
+
"dashboard"
|
|
16
|
+
],
|
|
5
17
|
"publishConfig": {
|
|
6
18
|
"access": "public"
|
|
7
19
|
},
|
|
@@ -40,15 +52,20 @@
|
|
|
40
52
|
"platform": "web"
|
|
41
53
|
},
|
|
42
54
|
"compatibility": {
|
|
43
|
-
"dsh": ">=0.1.
|
|
55
|
+
"dsh": ">=0.1.2-alpha.1",
|
|
44
56
|
"dshReleases": {
|
|
45
|
-
"0.1.
|
|
46
|
-
"0.1.
|
|
47
|
-
"0.1.
|
|
57
|
+
"0.1.2-alpha.1": "compatible",
|
|
58
|
+
"0.1.2-alpha.2": "compatible",
|
|
59
|
+
"0.1.2-alpha.3": "compatible",
|
|
60
|
+
"0.1.2-alpha.4": "compatible",
|
|
61
|
+
"0.1.2-alpha.5": "compatible",
|
|
62
|
+
"0.1.2-rc.1": "compatible",
|
|
63
|
+
"0.1.3-alpha.1": "compatible"
|
|
48
64
|
}
|
|
49
65
|
}
|
|
50
66
|
},
|
|
51
67
|
"scripts": {
|
|
68
|
+
"build": "tsc -b tsconfig.json && tsdown",
|
|
52
69
|
"bundle": "tsdown",
|
|
53
70
|
"watch": "tsdown --watch",
|
|
54
71
|
"test": "vitest run"
|
|
@@ -56,7 +73,7 @@
|
|
|
56
73
|
"license": "MIT",
|
|
57
74
|
"engines": {
|
|
58
75
|
"node": "^22.19.0 || >=24.0.0",
|
|
59
|
-
"dsh": ">=0.1.
|
|
76
|
+
"dsh": ">=0.1.2-alpha.1"
|
|
60
77
|
},
|
|
61
78
|
"peerDependencies": {
|
|
62
79
|
"@deepseek-ai/cordis": "*",
|
|
@@ -84,27 +101,30 @@
|
|
|
84
101
|
"clsx": "^2.1.1"
|
|
85
102
|
},
|
|
86
103
|
"devDependencies": {
|
|
87
|
-
"typescript": "^5.9.2",
|
|
88
104
|
"@deepseek-ai/cordis": "*",
|
|
89
105
|
"@deepseek-ai/cordis-plugin-include": "^1.0.7",
|
|
90
106
|
"@deepseek-ai/cordis-plugin-loader": "^1.0.3",
|
|
91
|
-
"@deepseek-ai/dsh-api-
|
|
92
|
-
"@deepseek-ai/dsh-api-
|
|
93
|
-
"@deepseek-ai/dsh-
|
|
94
|
-
"@deepseek-ai/dsh-
|
|
95
|
-
"@deepseek-ai/dsh-client-
|
|
96
|
-
"@deepseek-ai/dsh-client-
|
|
97
|
-
"@deepseek-ai/dsh-client-ui-
|
|
98
|
-
"@deepseek-ai/dsh-client-ui-
|
|
99
|
-
"@deepseek-ai/dsh-
|
|
100
|
-
"@deepseek-ai/dsh-
|
|
101
|
-
"@deepseek-ai/dsh-
|
|
102
|
-
"@deepseek-ai/dsh-
|
|
103
|
-
"@deepseek-ai/dsh-
|
|
104
|
-
"@deepseek-ai/dsh-
|
|
105
|
-
"@deepseek-ai/dsh-
|
|
106
|
-
"@deepseek-ai/dsh-
|
|
107
|
-
"@deepseek-ai/dsh-
|
|
107
|
+
"@deepseek-ai/dsh-api-gateway": "0.1.2-rc.1",
|
|
108
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.2-rc.1",
|
|
109
|
+
"@deepseek-ai/dsh-api-session-controller": "0.1.2-rc.1",
|
|
110
|
+
"@deepseek-ai/dsh-atomic-write": "0.1.2-rc.1",
|
|
111
|
+
"@deepseek-ai/dsh-client-locale": "0.1.2-rc.1",
|
|
112
|
+
"@deepseek-ai/dsh-client-store": "0.1.2-rc.1",
|
|
113
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1",
|
|
114
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1",
|
|
115
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.1.2-rc.1",
|
|
116
|
+
"@deepseek-ai/dsh-client-ui-sidebar": "0.1.2-rc.1",
|
|
117
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.2-rc.1",
|
|
118
|
+
"@deepseek-ai/dsh-credentials": "0.1.2-rc.1",
|
|
119
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.2-rc.1",
|
|
120
|
+
"@deepseek-ai/dsh-invariants": "0.1.2-rc.1",
|
|
121
|
+
"@deepseek-ai/dsh-llm": "0.1.2-rc.1",
|
|
122
|
+
"@deepseek-ai/dsh-scope": "0.1.2-rc.1",
|
|
123
|
+
"@deepseek-ai/dsh-session": "0.1.2-rc.1",
|
|
124
|
+
"@deepseek-ai/dsh-session-persistence": "0.1.2-rc.1",
|
|
125
|
+
"@deepseek-ai/dsh-settings": "0.1.2-rc.1",
|
|
126
|
+
"@deepseek-ai/dsh-tools": "0.1.2-rc.1",
|
|
127
|
+
"@deepseek-ai/dsh-typert-protocol": "0.1.2-rc.1",
|
|
108
128
|
"@deepseek-ai/schemastery": "^3.18.2",
|
|
109
129
|
"@testing-library/dom": "^10.4.1",
|
|
110
130
|
"@testing-library/react": "^16.1.0",
|
|
@@ -115,7 +135,9 @@
|
|
|
115
135
|
"lightningcss": "^1.32.0",
|
|
116
136
|
"react": "^18.2.0",
|
|
117
137
|
"react-dom": "^18.2.0",
|
|
138
|
+
"semver": "^7.7.2",
|
|
118
139
|
"tsdown": "^0.22.2",
|
|
140
|
+
"typescript": "^6.0.3",
|
|
119
141
|
"use-sync-external-store": "1.2.0",
|
|
120
142
|
"vitest": "^4.1.8"
|
|
121
143
|
},
|