@kenz1117/dsh-ui-usage-billing 1.1.4 → 1.1.6
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 +10 -0
- package/README.md +1 -1
- package/lib/client.js +2 -2
- package/lib/index.js +136 -63
- package/lib/types/aggregate.d.ts +1 -1
- package/lib/types/client/heatmap.d.ts +1 -1
- package/lib/types/client/round-chart.d.ts +1 -1
- package/package.json +43 -26
package/lib/index.js
CHANGED
|
@@ -266,7 +266,7 @@ function tierAt(timeMs) {
|
|
|
266
266
|
}
|
|
267
267
|
/** 时刻是否落在北京时间周末(周六/周日)。 */
|
|
268
268
|
function isBeijingWeekend(timeMs) {
|
|
269
|
-
const day = new Date(timeMs +
|
|
269
|
+
const day = new Date(timeMs + 288e5).getUTCDay();
|
|
270
270
|
return day === 0 || day === 6;
|
|
271
271
|
}
|
|
272
272
|
/**
|
|
@@ -1809,12 +1809,6 @@ function foldUsage(acc, usage, key, subscription, timeMs, official = false) {
|
|
|
1809
1809
|
}
|
|
1810
1810
|
}
|
|
1811
1811
|
/**
|
|
1812
|
-
* 联网搜索辅助请求的单次费用估算默认值(人民币元)。DeepSeek 官方对搜索请求
|
|
1813
|
-
* (web_search 服务端工具注入上下文)照常计费,实测每次约 0.01~0.03 元,取中值;
|
|
1814
|
-
* 部署可在插件配置 `searchCallEstimateCny` 覆盖(设 0 关闭估算)。
|
|
1815
|
-
*/
|
|
1816
|
-
const DEFAULT_SEARCH_CALL_ESTIMATE_CNY = .02;
|
|
1817
|
-
/**
|
|
1818
1812
|
* Fold one auxiliary web-search LLM request (issue #15) into an accumulator.
|
|
1819
1813
|
* 这类调用绕过对话通道直连官方端点,日志只记请求(无响应/用量事件),token
|
|
1820
1814
|
* 不可知:按「每次估值」计入费用并单独累计 `searchCalls`,不产生 token 维度。
|
|
@@ -2021,26 +2015,22 @@ function turnState(turns, turn) {
|
|
|
2021
2015
|
turns.set(turn, fresh);
|
|
2022
2016
|
return fresh;
|
|
2023
2017
|
}
|
|
2024
|
-
/**
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
* @returns the per-session fold (cached by the incremental aggregator).
|
|
2041
|
-
*/
|
|
2042
|
-
function foldSession(events, subscriptionProviders, officialProviderIds, routes = {}, searchCallEstimateCny = DEFAULT_SEARCH_CALL_ESTIMATE_CNY, seedLength = 0) {
|
|
2043
|
-
const fold = {
|
|
2018
|
+
/** 空白折叠状态机(与全量折叠的初值逐字一致)。 */
|
|
2019
|
+
function freshMachine() {
|
|
2020
|
+
return {
|
|
2021
|
+
key: "other",
|
|
2022
|
+
subscription: false,
|
|
2023
|
+
official: false,
|
|
2024
|
+
siteBucket: "unknown",
|
|
2025
|
+
turns: /* @__PURE__ */ new Map(),
|
|
2026
|
+
steps: /* @__PURE__ */ new Map(),
|
|
2027
|
+
lastOpenStepKey: void 0,
|
|
2028
|
+
toolSeen: /* @__PURE__ */ new Set()
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
2031
|
+
/** 空白 fold 的统一构造:foldSession 与聚合器的分片/增量路径共用同一字段初值。 */
|
|
2032
|
+
function freshFold() {
|
|
2033
|
+
return {
|
|
2044
2034
|
total: emptyUsage(),
|
|
2045
2035
|
byModel: /* @__PURE__ */ new Map(),
|
|
2046
2036
|
byDay: /* @__PURE__ */ new Map(),
|
|
@@ -2061,14 +2051,28 @@ function foldSession(events, subscriptionProviders, officialProviderIds, routes
|
|
|
2061
2051
|
},
|
|
2062
2052
|
lastActive: 0
|
|
2063
2053
|
};
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2054
|
+
}
|
|
2055
|
+
/**
|
|
2056
|
+
* 把一批事件折进既有 fold(状态机跨批次延续)。全量折叠、超大会话的分片折叠、
|
|
2057
|
+
* 活跃会话的 seq 增量折叠共用同一段循环体,保证三种路径的字段语义逐字一致。
|
|
2058
|
+
* @param fold - 累计目标(原地修改)。
|
|
2059
|
+
* @param machine - 折叠状态机:进入时为上一批次末态,返回时为本批次末态。
|
|
2060
|
+
* @param events - 本批次事件(日志顺序)。
|
|
2061
|
+
* @param subscriptionProviders - provider ids billed through subscription plans.
|
|
2062
|
+
* @param officialProviderIds - 官方直连 provider 集合(undefined = 按 deepseek 前缀判定)。
|
|
2063
|
+
* @param routes - 当前 provider 路由视图(中转站归组)。
|
|
2064
|
+
* @param searchCallEstimateCny - 联网搜索请求的单次费用估算(人民币元)。
|
|
2065
|
+
* @param seedLength - fork 血缘边界(seq 低于它的事件是父会话种子,跳过)。
|
|
2066
|
+
*/
|
|
2067
|
+
function foldInto(fold, machine, events, subscriptionProviders, officialProviderIds, routes, searchCallEstimateCny, seedLength) {
|
|
2068
|
+
let key = machine.key;
|
|
2069
|
+
let subscription = machine.subscription;
|
|
2070
|
+
let official = machine.official;
|
|
2071
|
+
let siteBucket = machine.siteBucket;
|
|
2072
|
+
const turns = machine.turns;
|
|
2073
|
+
const steps = machine.steps;
|
|
2074
|
+
let lastOpenStepKey = machine.lastOpenStepKey;
|
|
2075
|
+
const toolSeen = machine.toolSeen;
|
|
2072
2076
|
for (const event of events) {
|
|
2073
2077
|
if (seedLength > 0 && typeof event.seq === "number" && Number.isFinite(event.seq) && event.seq < seedLength) continue;
|
|
2074
2078
|
fold.lastActive = Math.max(fold.lastActive, event.time);
|
|
@@ -2216,7 +2220,15 @@ function foldSession(events, subscriptionProviders, officialProviderIds, routes
|
|
|
2216
2220
|
}
|
|
2217
2221
|
}
|
|
2218
2222
|
}
|
|
2219
|
-
|
|
2223
|
+
machine.key = key;
|
|
2224
|
+
machine.subscription = subscription;
|
|
2225
|
+
machine.official = official;
|
|
2226
|
+
machine.siteBucket = siteBucket;
|
|
2227
|
+
machine.lastOpenStepKey = lastOpenStepKey;
|
|
2228
|
+
}
|
|
2229
|
+
/** 从轮次状态派生 fold.turns(每批次结束后重派生;半开轮次跨批次保留)。 */
|
|
2230
|
+
function refreshTurns(fold, machine) {
|
|
2231
|
+
fold.turns = [...machine.turns.values()].filter((state) => state.input > 0 || state.output > 0).sort((a, b) => a.turn - b.turn).map((state) => ({
|
|
2220
2232
|
turn: state.turn,
|
|
2221
2233
|
model: state.model,
|
|
2222
2234
|
input: state.input,
|
|
@@ -2227,7 +2239,6 @@ function foldSession(events, subscriptionProviders, officialProviderIds, routes
|
|
|
2227
2239
|
startedAt: state.startedAt === Number.MAX_SAFE_INTEGER ? fold.lastActive : state.startedAt,
|
|
2228
2240
|
...state.endedAt === void 0 ? {} : { endedAt: state.endedAt }
|
|
2229
2241
|
}));
|
|
2230
|
-
return fold;
|
|
2231
2242
|
}
|
|
2232
2243
|
/**
|
|
2233
2244
|
* 生成一个 step 的性能样本;无效 / 超出 sane 上限(15 分钟)时返回 undefined,
|
|
@@ -2307,6 +2318,23 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
2307
2318
|
/** 每次聚合取最新的 provider 路由视图(中转站零配置发现);缺省按空处理(全部未知路由)。 */
|
|
2308
2319
|
const routesOf = () => options.resolveRoutes?.() ?? {};
|
|
2309
2320
|
const searchEstimate = options.searchCallEstimateCny ?? .02;
|
|
2321
|
+
const FOLD_CHUNK_EVENTS = 8e3;
|
|
2322
|
+
/** 把一份(全量或增量)折叠结果登记进 durable ledger;内容无变化时不落盘。 */
|
|
2323
|
+
const recordLedger = (id, cwd, stamp, fold) => {
|
|
2324
|
+
if (options.ledger === void 0) return;
|
|
2325
|
+
const entry = {
|
|
2326
|
+
id,
|
|
2327
|
+
...cwd === void 0 ? {} : { cwd },
|
|
2328
|
+
...stamp === null ? {} : { stamp },
|
|
2329
|
+
foldVersion: 6,
|
|
2330
|
+
fold: serializeFold(fold)
|
|
2331
|
+
};
|
|
2332
|
+
const row = ledger.get(id);
|
|
2333
|
+
if (row === void 0 || row.stamp !== entry.stamp || row.cwd !== entry.cwd || row.foldVersion !== entry.foldVersion || stamp === null && JSON.stringify(row.fold) !== JSON.stringify(entry.fold)) {
|
|
2334
|
+
ledger.set(id, entry);
|
|
2335
|
+
ledgerNeedsSave = true;
|
|
2336
|
+
}
|
|
2337
|
+
};
|
|
2310
2338
|
const ensureLedgerLoaded = async () => {
|
|
2311
2339
|
if (ledgerLoaded || options.ledger === void 0) return;
|
|
2312
2340
|
ledgerLoaded = true;
|
|
@@ -2368,34 +2396,78 @@ function createUsageAggregator(persistence, options = {}) {
|
|
|
2368
2396
|
continue;
|
|
2369
2397
|
}
|
|
2370
2398
|
try {
|
|
2399
|
+
const cwd = meta.cwd;
|
|
2400
|
+
const ledgerRow = ledger.get(id);
|
|
2401
|
+
if (ledgerRow !== void 0 && ledgerRow.stamp !== void 0 && stamp !== null && ledgerRow.stamp === stamp && (ledgerRow.foldVersion ?? 1) === 6) {
|
|
2402
|
+
const fold = deserializeFold(ledgerRow.fold);
|
|
2403
|
+
cache.set(id, {
|
|
2404
|
+
stamp,
|
|
2405
|
+
fold
|
|
2406
|
+
});
|
|
2407
|
+
folds.push({
|
|
2408
|
+
id,
|
|
2409
|
+
...cwd === void 0 ? {} : { cwd },
|
|
2410
|
+
fold
|
|
2411
|
+
});
|
|
2412
|
+
included.add(id);
|
|
2413
|
+
continue;
|
|
2414
|
+
}
|
|
2415
|
+
const previous = cache.get(id);
|
|
2416
|
+
if (previous?.machine !== void 0 && previous.lastSeq !== void 0) {
|
|
2417
|
+
const from = previous.lastSeq + 1;
|
|
2418
|
+
const { events } = await persistence.readFrom(meta.id, from);
|
|
2419
|
+
const after = await stampOf(meta);
|
|
2420
|
+
if (stamp !== null && after !== stamp) {
|
|
2421
|
+
cache.delete(id);
|
|
2422
|
+
continue;
|
|
2423
|
+
}
|
|
2424
|
+
const first = events[0]?.seq;
|
|
2425
|
+
if (events.length === 0 || first !== from) {
|
|
2426
|
+
cache.delete(id);
|
|
2427
|
+
continue;
|
|
2428
|
+
}
|
|
2429
|
+
foldInto(previous.fold, previous.machine, events, subscriptionProviders, officialProviderIds, routesOf(), searchEstimate, meta.seedLength ?? 0);
|
|
2430
|
+
refreshTurns(previous.fold, previous.machine);
|
|
2431
|
+
const last = events[events.length - 1];
|
|
2432
|
+
previous.lastSeq = typeof last.seq === "number" ? last.seq : previous.lastSeq;
|
|
2433
|
+
previous.stamp = stamp;
|
|
2434
|
+
cache.delete(id);
|
|
2435
|
+
cache.set(id, previous);
|
|
2436
|
+
folds.push({
|
|
2437
|
+
id,
|
|
2438
|
+
...cwd === void 0 ? {} : { cwd },
|
|
2439
|
+
fold: previous.fold
|
|
2440
|
+
});
|
|
2441
|
+
included.add(id);
|
|
2442
|
+
recordLedger(id, cwd, stamp, previous.fold);
|
|
2443
|
+
continue;
|
|
2444
|
+
}
|
|
2371
2445
|
const { events } = await persistence.readFrom(meta.id, 0);
|
|
2372
2446
|
const after = await stampOf(meta);
|
|
2373
2447
|
if (stamp !== null && after !== stamp) continue;
|
|
2374
|
-
const fold =
|
|
2448
|
+
const fold = freshFold();
|
|
2449
|
+
const machine = freshMachine();
|
|
2450
|
+
for (let start = 0; start < events.length; start += FOLD_CHUNK_EVENTS) {
|
|
2451
|
+
foldInto(fold, machine, events.slice(start, start + FOLD_CHUNK_EVENTS), subscriptionProviders, officialProviderIds, routesOf(), searchEstimate, meta.seedLength ?? 0);
|
|
2452
|
+
if (start + FOLD_CHUNK_EVENTS < events.length) await new Promise((resolve) => {
|
|
2453
|
+
setImmediate(resolve);
|
|
2454
|
+
});
|
|
2455
|
+
}
|
|
2456
|
+
refreshTurns(fold, machine);
|
|
2457
|
+
const last = events[events.length - 1];
|
|
2375
2458
|
cache.set(id, {
|
|
2376
2459
|
stamp,
|
|
2377
|
-
fold
|
|
2460
|
+
fold,
|
|
2461
|
+
machine,
|
|
2462
|
+
...last !== void 0 && typeof last.seq === "number" ? { lastSeq: last.seq } : {}
|
|
2378
2463
|
});
|
|
2379
2464
|
folds.push({
|
|
2380
2465
|
id,
|
|
2381
|
-
...
|
|
2466
|
+
...cwd === void 0 ? {} : { cwd },
|
|
2382
2467
|
fold
|
|
2383
2468
|
});
|
|
2384
2469
|
included.add(id);
|
|
2385
|
-
|
|
2386
|
-
const entry = {
|
|
2387
|
-
id,
|
|
2388
|
-
...meta.cwd === void 0 ? {} : { cwd: meta.cwd },
|
|
2389
|
-
...stamp === null ? {} : { stamp },
|
|
2390
|
-
foldVersion: 6,
|
|
2391
|
-
fold: serializeFold(fold)
|
|
2392
|
-
};
|
|
2393
|
-
const previous = ledger.get(id);
|
|
2394
|
-
if (previous === void 0 || previous.stamp !== entry.stamp || previous.cwd !== entry.cwd || previous.foldVersion !== entry.foldVersion || stamp === null && JSON.stringify(previous.fold) !== JSON.stringify(entry.fold)) {
|
|
2395
|
-
ledger.set(id, entry);
|
|
2396
|
-
ledgerNeedsSave = true;
|
|
2397
|
-
}
|
|
2398
|
-
}
|
|
2470
|
+
recordLedger(id, cwd, stamp, fold);
|
|
2399
2471
|
} catch (error) {
|
|
2400
2472
|
skipped.push(id);
|
|
2401
2473
|
console.warn("[usage-billing] skip unreadable session", id, error);
|
|
@@ -3222,7 +3294,7 @@ const declaredGate = createCooldownGate({
|
|
|
3222
3294
|
cooldownMs: 6e4
|
|
3223
3295
|
});
|
|
3224
3296
|
/** 会触及原型链的路径段:一律拒绝(读结果不是文档自带字段)。 */
|
|
3225
|
-
const FORBIDDEN_SEGMENTS = new Set([
|
|
3297
|
+
const FORBIDDEN_SEGMENTS = /* @__PURE__ */ new Set([
|
|
3226
3298
|
"__proto__",
|
|
3227
3299
|
"constructor",
|
|
3228
3300
|
"prototype"
|
|
@@ -3772,7 +3844,7 @@ function asPrice(value) {
|
|
|
3772
3844
|
*/
|
|
3773
3845
|
function buildExtraModels(data) {
|
|
3774
3846
|
if (data === null || typeof data !== "object") return [];
|
|
3775
|
-
const catalogKeys = new Set([...MODEL_CATALOG.map((entry) => entry.key.toLowerCase()), ...Object.keys(MODEL_KEY_ALIASES).map((key) => MODEL_KEY_ALIASES[key]?.toLowerCase() ?? key.toLowerCase())]);
|
|
3847
|
+
const catalogKeys = /* @__PURE__ */ new Set([...MODEL_CATALOG.map((entry) => entry.key.toLowerCase()), ...Object.keys(MODEL_KEY_ALIASES).map((key) => MODEL_KEY_ALIASES[key]?.toLowerCase() ?? key.toLowerCase())]);
|
|
3776
3848
|
const extras = [];
|
|
3777
3849
|
for (const [providerId, providerDoc] of Object.entries(data)) {
|
|
3778
3850
|
if (providerDoc === null || typeof providerDoc !== "object") continue;
|
|
@@ -4446,7 +4518,7 @@ const relayGate = createCooldownGate({
|
|
|
4446
4518
|
/** Abort a relay fetch when the upstream hangs beyond this budget. */
|
|
4447
4519
|
const FETCH_TIMEOUT_MS = 8e3;
|
|
4448
4520
|
/** 指纹识别缓存 TTL(毫秒):识别结果低频变化,5 分钟内同 origin 不再重复探测。 */
|
|
4449
|
-
const FINGERPRINT_TTL_MS =
|
|
4521
|
+
const FINGERPRINT_TTL_MS = 3e5;
|
|
4450
4522
|
/** 每 origin 的识别结果缓存:`kind` 是识别出的中转站程序,`at` 是探测时刻。 */
|
|
4451
4523
|
const fingerprintCache = /* @__PURE__ */ new Map();
|
|
4452
4524
|
/** Number, or null when the value is not a finite number (nor numeric string). */
|
|
@@ -4582,7 +4654,7 @@ function originOf(baseURL) {
|
|
|
4582
4654
|
* 子路径只会得到 404/非中转站格式,因而面板应排除它们,避免误判为
|
|
4583
4655
|
* 「未识别」。中转站面板只列真正的第三方中转程序。
|
|
4584
4656
|
*/
|
|
4585
|
-
const OFFICIAL_HOSTS = new Set([
|
|
4657
|
+
const OFFICIAL_HOSTS = /* @__PURE__ */ new Set([
|
|
4586
4658
|
"api.deepseek.com",
|
|
4587
4659
|
"api.openai.com",
|
|
4588
4660
|
"open.bigmodel.cn",
|
|
@@ -4832,10 +4904,10 @@ const usageBillingSettingsNs = validateSettingsNamespace(BILLING_SETTINGS_NAMESP
|
|
|
4832
4904
|
/** 该命名空间的 wire schema:`enableUsageStatsTool` 布尔,默认关闭(issue 诉求)。 */
|
|
4833
4905
|
const UsageBillingSettingsSchema = z.object({ [ENABLE_USAGE_STATS_TOOL_FIELD]: z.boolean().default(false) });
|
|
4834
4906
|
/** 实时定价的后台刷新间隔(毫秒):汇率/模型价低频变化,6 小时一次足够。 */
|
|
4835
|
-
const PRICING_REFRESH_INTERVAL_MS =
|
|
4907
|
+
const PRICING_REFRESH_INTERVAL_MS = 216e5;
|
|
4836
4908
|
/** 订阅套餐额度缓存时长(毫秒):上游配额 API 低频变化,5 分钟足够。 */
|
|
4837
|
-
const SUBSCRIPTION_CACHE_MS =
|
|
4838
|
-
const BALANCE_CACHE_MS =
|
|
4909
|
+
const SUBSCRIPTION_CACHE_MS = 3e5;
|
|
4910
|
+
const BALANCE_CACHE_MS = 3e5;
|
|
4839
4911
|
/** DeepSeek 余额查询的默认凭据引用(与 llm-deepseek 的默认引用一致)。 */
|
|
4840
4912
|
const DEFAULT_BALANCE_API_KEY_ENV = "DEEPSEEK_API_KEY";
|
|
4841
4913
|
/**
|
|
@@ -4846,7 +4918,7 @@ const PACKAGE_VERSION = createRequire(import.meta.url)("../package.json").versio
|
|
|
4846
4918
|
/** 统计快照的落盘节流(毫秒):前端 30 秒轮询,快照最多每 30 秒写一次。 */
|
|
4847
4919
|
const SNAPSHOT_INTERVAL_MS = 3e4;
|
|
4848
4920
|
/** 鉴权失败告警冷却(毫秒):同一 provider 在窗口内只提示一次,避免 30 秒轮询刷屏。 */
|
|
4849
|
-
const AUTH_WARN_COOLDOWN_MS =
|
|
4921
|
+
const AUTH_WARN_COOLDOWN_MS = 18e5;
|
|
4850
4922
|
/**
|
|
4851
4923
|
* 鉴权失败分类告警(P1-5):余额 / 订阅查询返回 unauthorized 时,按
|
|
4852
4924
|
* `source:provider` 去重并冷却告警,提示检查 llm-pi-ai 里该 provider 的 apiKeyEnv。
|
|
@@ -5090,7 +5162,8 @@ function apply(ctx, config = {}) {
|
|
|
5090
5162
|
})();
|
|
5091
5163
|
const persistReconcileRef = () => {
|
|
5092
5164
|
if (reconcileRef === null) return;
|
|
5093
|
-
|
|
5165
|
+
const payload = JSON.stringify({ ref: reconcileRef });
|
|
5166
|
+
writeFileAtomic(reconcilePath, payload, {
|
|
5094
5167
|
mode: 384,
|
|
5095
5168
|
dirMode: 448
|
|
5096
5169
|
}).catch(() => {});
|
package/lib/types/aggregate.d.ts
CHANGED
|
@@ -479,7 +479,7 @@ export declare function messageTextLength(message: unknown): number;
|
|
|
479
479
|
export declare function foldSession(events: readonly {
|
|
480
480
|
type: string;
|
|
481
481
|
time: number;
|
|
482
|
-
data:
|
|
482
|
+
data: unknown;
|
|
483
483
|
seq?: number;
|
|
484
484
|
}[], subscriptionProviders: ReadonlySet<string>, officialProviderIds?: ReadonlySet<string>, routes?: Readonly<Record<string, ProviderRouteView>>, searchCallEstimateCny?: number, seedLength?: number): SessionFold;
|
|
485
485
|
/**
|
|
@@ -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
|
|
@@ -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
|
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.1.
|
|
4
|
+
"version": "1.1.6",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
},
|
|
35
35
|
"client": {
|
|
36
36
|
"inject": [
|
|
37
|
-
"@deepseek-ai/dsh-client-runtime",
|
|
38
37
|
"@deepseek-ai/dsh-client-locale",
|
|
39
38
|
"@deepseek-ai/dsh-client-ui-conversation"
|
|
40
39
|
],
|
|
41
40
|
"platform": "web"
|
|
42
41
|
},
|
|
43
42
|
"compatibility": {
|
|
43
|
+
"dsh": ">=0.1.0-rc.8 <0.1.1-0 || >=0.1.1-rc.1 <0.1.2-0",
|
|
44
44
|
"dshReleases": {
|
|
45
45
|
"0.1.0-rc.8": "compatible",
|
|
46
46
|
"0.1.1-rc.1": "compatible",
|
|
@@ -48,28 +48,23 @@
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
|
-
"scripts": {
|
|
52
|
-
"bundle": "tsdown",
|
|
53
|
-
"watch": "tsdown --watch",
|
|
54
|
-
"test": "vitest run",
|
|
55
|
-
"build": "bash build.sh"
|
|
56
|
-
},
|
|
57
51
|
"license": "MIT",
|
|
58
52
|
"engines": {
|
|
59
53
|
"node": "^22.19.0 || >=24.0.0"
|
|
60
54
|
},
|
|
61
55
|
"peerDependencies": {
|
|
56
|
+
"@deepseek-ai/cordis": "*",
|
|
62
57
|
"@deepseek-ai/dsh-api-remotes": "*",
|
|
58
|
+
"@deepseek-ai/dsh-api-session-controller": "*",
|
|
63
59
|
"@deepseek-ai/dsh-atomic-write": "*",
|
|
64
|
-
"@deepseek-ai/dsh-client-connection": "*",
|
|
65
|
-
"@deepseek-ai/dsh-host-webserver": "*",
|
|
66
60
|
"@deepseek-ai/dsh-client-locale": "*",
|
|
67
|
-
"@deepseek-ai/dsh-client-
|
|
61
|
+
"@deepseek-ai/dsh-client-store": "*",
|
|
68
62
|
"@deepseek-ai/dsh-client-ui-conversation": "*",
|
|
69
|
-
"@deepseek-ai/dsh-client-ui-sidebar": "*",
|
|
70
63
|
"@deepseek-ai/dsh-client-ui-primitives": "*",
|
|
64
|
+
"@deepseek-ai/dsh-client-ui-sidebar": "*",
|
|
71
65
|
"@deepseek-ai/dsh-client-ui-slots": "*",
|
|
72
66
|
"@deepseek-ai/dsh-credentials": "*",
|
|
67
|
+
"@deepseek-ai/dsh-host-webserver": "*",
|
|
73
68
|
"@deepseek-ai/dsh-invariants": "*",
|
|
74
69
|
"@deepseek-ai/dsh-llm": "*",
|
|
75
70
|
"@deepseek-ai/dsh-session": "*",
|
|
@@ -77,28 +72,45 @@
|
|
|
77
72
|
"@deepseek-ai/dsh-settings": "*",
|
|
78
73
|
"@deepseek-ai/dsh-tools": "*",
|
|
79
74
|
"@deepseek-ai/schemastery": "*",
|
|
80
|
-
"@deepseek-ai/cordis": "*",
|
|
81
75
|
"react": "^18.2.0"
|
|
82
76
|
},
|
|
83
77
|
"dependencies": {
|
|
84
78
|
"clsx": "^2.1.1"
|
|
85
79
|
},
|
|
86
80
|
"devDependencies": {
|
|
87
|
-
"
|
|
88
|
-
"@deepseek-ai/
|
|
89
|
-
"@deepseek-ai/
|
|
90
|
-
"@deepseek-ai/
|
|
91
|
-
"@deepseek-ai/dsh-
|
|
92
|
-
"@deepseek-ai/dsh-
|
|
93
|
-
"@deepseek-ai/dsh-
|
|
81
|
+
"typescript": "^5.9.2",
|
|
82
|
+
"@deepseek-ai/cordis": "*",
|
|
83
|
+
"@deepseek-ai/cordis-plugin-include": "^1.0.7",
|
|
84
|
+
"@deepseek-ai/cordis-plugin-loader": "^1.0.3",
|
|
85
|
+
"@deepseek-ai/dsh-api-remotes": "0.1.2-alpha.5",
|
|
86
|
+
"@deepseek-ai/dsh-api-session-controller": "0.1.2-alpha.5",
|
|
87
|
+
"@deepseek-ai/dsh-atomic-write": "0.1.2-alpha.5",
|
|
88
|
+
"@deepseek-ai/dsh-client-locale": "0.1.2-alpha.5",
|
|
89
|
+
"@deepseek-ai/dsh-client-store": "0.1.2-alpha.5",
|
|
90
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.2-alpha.5",
|
|
91
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.2-alpha.5",
|
|
92
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.2-alpha.5",
|
|
93
|
+
"@deepseek-ai/dsh-credentials": "0.1.2-alpha.5",
|
|
94
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.2-alpha.5",
|
|
95
|
+
"@deepseek-ai/dsh-invariants": "0.1.2-alpha.5",
|
|
96
|
+
"@deepseek-ai/dsh-llm": "0.1.2-alpha.5",
|
|
97
|
+
"@deepseek-ai/dsh-scope": "0.1.2-alpha.5",
|
|
98
|
+
"@deepseek-ai/dsh-session": "0.1.2-alpha.5",
|
|
99
|
+
"@deepseek-ai/dsh-session-persistence": "0.1.2-alpha.5",
|
|
100
|
+
"@deepseek-ai/dsh-settings": "0.1.2-alpha.5",
|
|
101
|
+
"@deepseek-ai/dsh-tools": "0.1.2-alpha.5",
|
|
102
|
+
"@deepseek-ai/schemastery": "^3.18.2",
|
|
103
|
+
"@testing-library/dom": "^10.4.1",
|
|
94
104
|
"@testing-library/react": "^16.1.0",
|
|
95
|
-
"@types/react": "~18.3.1",
|
|
96
105
|
"@types/node": "^22.20.0",
|
|
97
|
-
"@
|
|
106
|
+
"@types/react": "~18.3.1",
|
|
107
|
+
"jsdom": "^26.1.0",
|
|
108
|
+
"lightningcss": "^1.32.0",
|
|
98
109
|
"react": "^18.2.0",
|
|
99
110
|
"react-dom": "^18.2.0",
|
|
100
|
-
"
|
|
101
|
-
"
|
|
111
|
+
"tsdown": "^0.22.2",
|
|
112
|
+
"use-sync-external-store": "1.2.0",
|
|
113
|
+
"vitest": "^4.1.8"
|
|
102
114
|
},
|
|
103
115
|
"files": [
|
|
104
116
|
"lib/index.js",
|
|
@@ -106,5 +118,10 @@
|
|
|
106
118
|
"lib/client.js",
|
|
107
119
|
"lib/types/**/*.d.ts",
|
|
108
120
|
"cordis.patch.yml"
|
|
109
|
-
]
|
|
110
|
-
|
|
121
|
+
],
|
|
122
|
+
"scripts": {
|
|
123
|
+
"bundle": "tsdown",
|
|
124
|
+
"watch": "tsdown --watch",
|
|
125
|
+
"test": "vitest run"
|
|
126
|
+
}
|
|
127
|
+
}
|