@kenz1117/dsh-ui-usage-billing 1.4.19 → 1.4.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -2422,8 +2422,10 @@ function emptyUsage() {
2422
2422
  * @param pricedCost - 调用方预算好的本次费用(同一条消息折叠进多个桶时计价结果相同,
2423
2423
  * 逐桶重算会让最热路径付出 N 倍常数);提供时跳过内部的计价闸门与计算,
2424
2424
  * 调用方保证其已按 `!subscription && isPriced(key)` 判定。
2425
+ * @param unverifiedChannel - 本次调用是否来自未知通道(配置外 provider)。未知通道的
2426
+ * 支出主体无法核实,费用一律记 0(token 照常统计,issue #82)。
2425
2427
  */
2426
- function foldUsage(acc, usage, key, subscription, timeMs, official = false, pricedCost) {
2428
+ function foldUsage(acc, usage, key, subscription, timeMs, official = false, pricedCost, unverifiedChannel = false) {
2427
2429
  const cacheHit = usage.cacheReadTokens ?? 0;
2428
2430
  const cacheMiss = usage.inputTokens + (usage.cacheWriteTokens ?? 0);
2429
2431
  acc.calls += 1;
@@ -2439,7 +2441,7 @@ function foldUsage(acc, usage, key, subscription, timeMs, official = false, pric
2439
2441
  if (official) acc.officialCost += pricedCost;
2440
2442
  return;
2441
2443
  }
2442
- if (!subscription && isPriced(key)) {
2444
+ if (!subscription && !unverifiedChannel && isPriced(key)) {
2443
2445
  const thisCost = computeCostAt(modelOf(key), {
2444
2446
  input: cacheHit + cacheMiss,
2445
2447
  cacheHit,
@@ -2718,6 +2720,7 @@ function serializeFold(fold) {
2718
2720
  bySite: Object.fromEntries(fold.bySite),
2719
2721
  unpricedModels: [...fold.unpricedModels],
2720
2722
  planCalls: Object.fromEntries(fold.planCalls),
2723
+ planSiteCalls: Object.fromEntries(fold.planSiteCalls),
2721
2724
  turns: fold.turns,
2722
2725
  perfDigest,
2723
2726
  perfHourDigest,
@@ -2739,6 +2742,7 @@ function deserializeFold(fold) {
2739
2742
  bySite: new Map(Object.entries(fold.bySite)),
2740
2743
  unpricedModels: new Set(fold.unpricedModels),
2741
2744
  planCalls: new Map(Object.entries(fold.planCalls)),
2745
+ planSiteCalls: new Map(Object.entries(fold.planSiteCalls ?? {})),
2742
2746
  turns: fold.turns,
2743
2747
  perf: [],
2744
2748
  perfDigest: new Map(Object.entries(fold.perfDigest)),
@@ -2794,6 +2798,14 @@ function modelDayCell(map, day, modelKey) {
2794
2798
  }
2795
2799
  return usageCell(models, modelKey);
2796
2800
  }
2801
+ /** 订阅计数的三维键:日期×模型×站点三元组的 JSON 形态(免分隔符转义歧义)。 */
2802
+ function planSiteKey(day, modelKey, siteKey) {
2803
+ return JSON.stringify([
2804
+ day,
2805
+ modelKey,
2806
+ siteKey
2807
+ ]);
2808
+ }
2797
2809
  /** Get-or-create one day×model×site cell inside the three-dimensional map. */
2798
2810
  function modelDaySiteCell(map, day, modelKey, siteKey) {
2799
2811
  let models = map.get(day);
@@ -2851,6 +2863,7 @@ function freshFold() {
2851
2863
  bySite: /* @__PURE__ */ new Map(),
2852
2864
  unpricedModels: /* @__PURE__ */ new Set(),
2853
2865
  planCalls: /* @__PURE__ */ new Map(),
2866
+ planSiteCalls: /* @__PURE__ */ new Map(),
2854
2867
  turns: [],
2855
2868
  perf: [],
2856
2869
  perfDigest: /* @__PURE__ */ new Map(),
@@ -2994,8 +3007,9 @@ function foldInto(fold, machine, events, subscriptionProviders, officialProvider
2994
3007
  }
2995
3008
  const modelKey = key;
2996
3009
  const day = dayStamp(event.time);
2997
- const priced = !subscription && isPriced(modelKey);
2998
- if (!subscription && !priced) fold.unpricedModels.add(modelKey);
3010
+ const unverifiedChannel = siteBucket === "unknown";
3011
+ const priced = !subscription && !unverifiedChannel && isPriced(modelKey);
3012
+ if (!subscription && !isPriced(modelKey)) fold.unpricedModels.add(modelKey);
2999
3013
  const entry = priced ? modelOf(modelKey) : void 0;
3000
3014
  const thisCost = entry === void 0 ? void 0 : computeCostAt(entry, {
3001
3015
  input: (usage.cacheReadTokens ?? 0) + usage.inputTokens + (usage.cacheWriteTokens ?? 0),
@@ -3003,14 +3017,18 @@ function foldInto(fold, machine, events, subscriptionProviders, officialProvider
3003
3017
  cacheMiss: usage.inputTokens + (usage.cacheWriteTokens ?? 0),
3004
3018
  output: usage.outputTokens
3005
3019
  }, event.time);
3006
- foldUsage(fold.total, usage, modelKey, subscription, event.time, official, thisCost);
3007
- foldUsage(usageCell(fold.byModel, modelKey), usage, modelKey, subscription, event.time, official, thisCost);
3008
- foldUsage(usageCell(fold.byDay, day), usage, modelKey, subscription, event.time, official, thisCost);
3009
- foldUsage(modelDayCell(fold.byDayModels, day, modelKey), usage, modelKey, subscription, event.time, official, thisCost);
3010
- foldUsage(modelDaySiteCell(fold.byDayModelsSite, day, modelKey, siteBucket), usage, modelKey, subscription, event.time, official, thisCost);
3011
- foldUsage(usageCell(fold.bySite, siteBucket), usage, modelKey, subscription, event.time, official, thisCost);
3012
- foldUsage(usageCell(fold.byTier, tierAt(event.time)), usage, modelKey, subscription, event.time, official, thisCost);
3020
+ foldUsage(fold.total, usage, modelKey, subscription, event.time, official, thisCost, unverifiedChannel);
3021
+ foldUsage(usageCell(fold.byModel, modelKey), usage, modelKey, subscription, event.time, official, thisCost, unverifiedChannel);
3022
+ foldUsage(usageCell(fold.byDay, day), usage, modelKey, subscription, event.time, official, thisCost, unverifiedChannel);
3023
+ foldUsage(modelDayCell(fold.byDayModels, day, modelKey), usage, modelKey, subscription, event.time, official, thisCost, unverifiedChannel);
3024
+ foldUsage(modelDaySiteCell(fold.byDayModelsSite, day, modelKey, siteBucket), usage, modelKey, subscription, event.time, official, thisCost, unverifiedChannel);
3025
+ foldUsage(usageCell(fold.bySite, siteBucket), usage, modelKey, subscription, event.time, official, thisCost, unverifiedChannel);
3026
+ foldUsage(usageCell(fold.byTier, tierAt(event.time)), usage, modelKey, subscription, event.time, official, thisCost, unverifiedChannel);
3013
3027
  if (subscription) fold.planCalls.set(modelKey, (fold.planCalls.get(modelKey) ?? 0) + 1);
3028
+ if (subscription) {
3029
+ const sitePlanKey = planSiteKey(day, modelKey, siteBucket);
3030
+ fold.planSiteCalls.set(sitePlanKey, (fold.planSiteCalls.get(sitePlanKey) ?? 0) + 1);
3031
+ }
3014
3032
  const turn = event.data.turn ?? -1;
3015
3033
  const state = turnState(turns, turn);
3016
3034
  state.model = modelKey;
@@ -3207,7 +3225,7 @@ function createUsageAggregator(persistence, options = {}) {
3207
3225
  id,
3208
3226
  ...cwd === void 0 ? {} : { cwd },
3209
3227
  ...stamp === null ? {} : { stamp },
3210
- foldVersion: 16,
3228
+ foldVersion: 18,
3211
3229
  fingerprint: foldFingerprint,
3212
3230
  fold: serializeFold(fold)
3213
3231
  };
@@ -3304,7 +3322,7 @@ function createUsageAggregator(persistence, options = {}) {
3304
3322
  try {
3305
3323
  const cwd = meta.cwd;
3306
3324
  const ledgerRow = ledger.get(id);
3307
- if (ledgerRow !== void 0 && ledgerRow.stamp !== void 0 && stamp !== null && ledgerRow.stamp === stamp && (ledgerRow.foldVersion ?? 1) === 16 && ledgerRow.fingerprint === foldFingerprint) {
3325
+ if (ledgerRow !== void 0 && ledgerRow.stamp !== void 0 && stamp !== null && ledgerRow.stamp === stamp && (ledgerRow.foldVersion ?? 1) === 18 && ledgerRow.fingerprint === foldFingerprint) {
3308
3326
  const fold = deserializeFold(ledgerRow.fold);
3309
3327
  folds.push({
3310
3328
  id,
@@ -3386,7 +3404,7 @@ function createUsageAggregator(persistence, options = {}) {
3386
3404
  for (const entry of ledger.values()) {
3387
3405
  if (included.has(entry.id)) continue;
3388
3406
  try {
3389
- const stale = (entry.foldVersion ?? 1) < 16 || entry.fingerprint !== foldFingerprint;
3407
+ const stale = (entry.foldVersion ?? 1) < 18 || entry.fingerprint !== foldFingerprint;
3390
3408
  folds.push({
3391
3409
  id: entry.id,
3392
3410
  ...entry.cwd === void 0 ? {} : { cwd: entry.cwd },
@@ -3412,6 +3430,7 @@ function createUsageAggregator(persistence, options = {}) {
3412
3430
  const bySite = /* @__PURE__ */ new Map();
3413
3431
  const unpricedModels = /* @__PURE__ */ new Set();
3414
3432
  const planCalls = /* @__PURE__ */ new Map();
3433
+ const planSiteCalls = /* @__PURE__ */ new Map();
3415
3434
  const sessionRows = [];
3416
3435
  const turnRows = [];
3417
3436
  const workspaceMap = /* @__PURE__ */ new Map();
@@ -3440,6 +3459,7 @@ function createUsageAggregator(persistence, options = {}) {
3440
3459
  for (const [toolName, count] of fold.byTool) byTool.set(toolName, (byTool.get(toolName) ?? 0) + count);
3441
3460
  for (const id of fold.unpricedModels) unpricedModels.add(id);
3442
3461
  for (const [modelKey, count] of fold.planCalls) planCalls.set(modelKey, (planCalls.get(modelKey) ?? 0) + count);
3462
+ for (const [key, count] of fold.planSiteCalls) planSiteCalls.set(key, (planSiteCalls.get(key) ?? 0) + count);
3443
3463
  for (const sample of fold.perf) {
3444
3464
  let modelAccum = perfModel.get(sample.model);
3445
3465
  if (modelAccum === void 0) {
@@ -3522,7 +3542,12 @@ function createUsageAggregator(persistence, options = {}) {
3522
3542
  return record;
3523
3543
  };
3524
3544
  const toModelDayRecord = (map) => Object.fromEntries([...map].map(([day, models]) => [day, Object.fromEntries(models)]));
3525
- const toModelDaySiteRecord = (map) => Object.fromEntries([...map].map(([day, models]) => [day, Object.fromEntries([...models].map(([model, sites]) => [model, Object.fromEntries(sites)]))]));
3545
+ const toModelDaySiteRecord = (map) => Object.fromEntries([...map].map(([day, models]) => [day, Object.fromEntries([...models].map(([model, sites]) => [model, Object.fromEntries([...sites].map(([site, cell]) => {
3546
+ return [site, (planSiteCalls.get(planSiteKey(day, model, site)) ?? 0) === cell.calls && cell.calls > 0 ? {
3547
+ ...cell,
3548
+ plan: true
3549
+ } : cell];
3550
+ }))]))]));
3526
3551
  const modelKeys = /* @__PURE__ */ new Set([...perfModel.keys(), ...perfModelDigest.keys()]);
3527
3552
  const hourKeys = /* @__PURE__ */ new Set([...perfHourModel.keys(), ...perfHourDigest.keys()]);
3528
3553
  const perf = modelKeys.size === 0 && hourKeys.size === 0 ? void 0 : {
@@ -174,8 +174,10 @@ export declare function emptyUsage(): ModelUsage;
174
174
  * @param pricedCost - 调用方预算好的本次费用(同一条消息折叠进多个桶时计价结果相同,
175
175
  * 逐桶重算会让最热路径付出 N 倍常数);提供时跳过内部的计价闸门与计算,
176
176
  * 调用方保证其已按 `!subscription && isPriced(key)` 判定。
177
+ * @param unverifiedChannel - 本次调用是否来自未知通道(配置外 provider)。未知通道的
178
+ * 支出主体无法核实,费用一律记 0(token 照常统计,issue #82)。
177
179
  */
178
- export declare function foldUsage(acc: ModelUsage, usage: TokenUsage, key: string, subscription: boolean, timeMs: number, official?: boolean, pricedCost?: number): void;
180
+ export declare function foldUsage(acc: ModelUsage, usage: TokenUsage, key: string, subscription: boolean, timeMs: number, official?: boolean, pricedCost?: number, unverifiedChannel?: boolean): void;
179
181
  /**
180
182
  * 联网搜索辅助请求的单次费用估算默认值(人民币元)。DeepSeek 官方对搜索请求
181
183
  * (web_search 服务端工具注入上下文)照常计费,实测每次约 0.01~0.03 元,取中值;
@@ -462,6 +464,10 @@ export interface SessionFold {
462
464
  unpricedModels: Set<string>;
463
465
  /** 每个模型 key 在本会话内走订阅通道的调用数(合并时跨会话累加判定 plan)。 */
464
466
  planCalls: Map<string, number>;
467
+ /** 三维格(日期×模型×站点)各自的订阅调用数,键 = {@link planSiteKey}:
468
+ * provider 视图的行 plan 按本格判定,不再借模型全局口径(混通道模型会把
469
+ * 本格全订阅的行判成无标记)。 */
470
+ planSiteCalls: Map<string, number>;
465
471
  /** 每轮费用明细(按轮次号升序,不含 sessionId);sessionId 在合并时补齐。 */
466
472
  turns: SessionTurnRow[];
467
473
  /** 性能样本(有可测 TTFT 的调用,按事件次序折叠);仅进程内折叠产生,
@@ -503,6 +509,8 @@ export interface SerializedSessionFold {
503
509
  bySite: Record<string, ModelUsage>;
504
510
  unpricedModels: string[];
505
511
  planCalls: Record<string, number>;
512
+ /** 三维格订阅计数;旧账本行缺失(合并按空处理,格级 plan 保守不置位)。 */
513
+ planSiteCalls?: Record<string, number>;
506
514
  turns: SessionTurnRow[];
507
515
  /** v16 起以摘要持久化性能(体积 O(模型数) 而非 O(样本数));旧行的
508
516
  * `perf` 逐样本数组由加载边界迁移转换为摘要。 */
@@ -552,7 +560,7 @@ export interface UsageLedgerDocument {
552
560
  * 会话费用只剩最近一段,issue #29)。
553
561
  * 持久账本行据此区分新旧算法:日志已删/不可读而只能沿用旧行时,UI 标注置信度提示。
554
562
  */
555
- export declare const FOLD_VERSION = 16;
563
+ export declare const FOLD_VERSION = 18;
556
564
  /**
557
565
  * 一次性账本迁移:id 唯一,apply 在加载边界对原始文档执行,已应用过的跳过。
558
566
  * 未来账本/schema 字段变更(重命名、拆桶、语义调整)时,在此追加一条迁移并
@@ -250,6 +250,8 @@ export interface UsageStats {
250
250
  cacheHit: number;
251
251
  cacheMiss: number;
252
252
  cost: number;
253
+ /** 该格全部调用都走订阅通道(聚合侧按三维格置位);旧快照缺失,回退全局口径。 */
254
+ plan?: boolean;
253
255
  }>>>;
254
256
  /**
255
257
  * 峰谷分桶(全量逐调用真实判档):1.0.8 起服务端按调用时刻精确归桶,
@@ -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' | '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' | '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' | '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' | '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' | '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' | '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' | '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>;
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.4.19",
4
+ "version": "1.4.21",
5
5
  "keywords": [
6
6
  "deepseek-harness",
7
7
  "deepseek",