@kenz1117/dsh-ui-usage-billing 1.0.41 → 1.0.43

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
@@ -238,6 +238,31 @@ const PEAK_ERA_START_MS = Date.parse("2026-08-16T16:00:00Z");
238
238
  */
239
239
  const WEEKEND_OFFPEAK_START_MS = Date.parse("2026-08-22T16:00:00Z");
240
240
  /**
241
+ * flash 系调价分界(UTC 2026-09-10T04:00:00Z,即北京时间 2026-09-10 12:00):
242
+ * 官方自此刻起 V4 Flash / V4 Flash Vision (Exp) 调价——谷档 1.5/0.05/4.5 →
243
+ * 1/0.02/4(峰 = 谷 × 2)。目录条目写现行(新)价;分界前的历史事件由
244
+ * {@link computeCostAt} 按 {@link FLASH_REPRICED_OFFPEAK} 回算旧价,与
245
+ * {@link PEAK_ERA_START_MS} 同一「按事件时刻分段适用规则」口径。
246
+ */
247
+ const FLASH_REPRICE_MS = Date.parse("2026-09-10T04:00:00Z");
248
+ /**
249
+ * flash 系调价前的官方谷档价(CNY / 1M tokens):{@link FLASH_REPRICE_MS}
250
+ * 之前的 flash / flash-vision-exp 事件按此回算(峰档 = 谷档 × 2)。
251
+ * 用户价 = 实付价,与 legacy 口径相同地跳过本表。
252
+ */
253
+ const FLASH_REPRICED_OFFPEAK = {
254
+ flash: {
255
+ input: 1.5,
256
+ cacheHit: .05,
257
+ output: 4.5
258
+ },
259
+ "flash-vision-exp": {
260
+ input: 1.5,
261
+ cacheHit: .05,
262
+ output: 4.5
263
+ }
264
+ };
265
+ /**
241
266
  * DeepSeek V4 峰谷时代之前的官方基础价(CNY / 1M tokens):官方中文定价页
242
267
  * 峰谷改版前的基础价档(缓存写沿用历史规则按命中价计)。键为内置目录键,
243
268
  * flash-vision-exp 与 flash 同价。仅当事件时刻早于 {@link PEAK_ERA_START_MS}
@@ -308,13 +333,13 @@ const MODEL_CATALOG = [
308
333
  colorVar: "dsw-static-blue-500",
309
334
  price: {
310
335
  currency: "CNY",
311
- input: 3,
312
- cacheHit: .1,
313
- output: 9,
336
+ input: 2,
337
+ cacheHit: .04,
338
+ output: 8,
314
339
  offPeak: {
315
- input: 1.5,
316
- cacheHit: .05,
317
- output: 4.5
340
+ input: 1,
341
+ cacheHit: .02,
342
+ output: 4
318
343
  }
319
344
  },
320
345
  peakHours: "09:00-12:00 / 14:00-18:00"
@@ -326,13 +351,13 @@ const MODEL_CATALOG = [
326
351
  colorVar: "dsw-static-blue-500",
327
352
  price: {
328
353
  currency: "CNY",
329
- input: 3,
330
- cacheHit: .1,
331
- output: 9,
354
+ input: 2,
355
+ cacheHit: .04,
356
+ output: 8,
332
357
  offPeak: {
333
- input: 1.5,
334
- cacheHit: .05,
335
- output: 4.5
358
+ input: 1,
359
+ cacheHit: .02,
360
+ output: 4
336
361
  }
337
362
  },
338
363
  peakHours: "09:00-12:00 / 14:00-18:00"
@@ -1725,6 +1750,12 @@ function computeCostAt(entry, buckets, timeMs, peakShare = DEFAULT_PEAK_SHARE) {
1725
1750
  const priced = applyPromo(entry, timeMs);
1726
1751
  const legacy = timeMs < PEAK_ERA_START_MS && entry.userPriced !== true ? LEGACY_DEEPSEEK_BANDS[entry.key] : void 0;
1727
1752
  if (legacy !== void 0) return priceBandCost(legacy, buckets, "CNY");
1753
+ const repriced = timeMs < FLASH_REPRICE_MS && entry.userPriced !== true ? FLASH_REPRICED_OFFPEAK[entry.key] : void 0;
1754
+ if (repriced !== void 0) return priceBandCost((timeMs < WEEKEND_OFFPEAK_START_MS ? tariffV1At(timeMs) : tierAt(timeMs)) === "peak" ? {
1755
+ input: repriced.input * 2,
1756
+ cacheHit: repriced.cacheHit * 2,
1757
+ output: repriced.output * 2
1758
+ } : repriced, buckets, "CNY");
1728
1759
  if (priced.price.offPeak === void 0) return priceBandCost(priced.price, buckets, priced.price.currency);
1729
1760
  return priceBandCost((timeMs < WEEKEND_OFFPEAK_START_MS ? tariffV1At(timeMs) : tierAt(timeMs)) === "peak" ? priced.price : priced.price.offPeak, buckets, priced.price.currency);
1730
1761
  }
@@ -2459,7 +2490,7 @@ function createUsageAggregator(persistence, options = {}) {
2459
2490
  id,
2460
2491
  ...cwd === void 0 ? {} : { cwd },
2461
2492
  ...stamp === null ? {} : { stamp },
2462
- foldVersion: 10,
2493
+ foldVersion: 11,
2463
2494
  fingerprint: foldFingerprint,
2464
2495
  fold: serializeFold(fold)
2465
2496
  };
@@ -2556,7 +2587,7 @@ function createUsageAggregator(persistence, options = {}) {
2556
2587
  try {
2557
2588
  const cwd = meta.cwd;
2558
2589
  const ledgerRow = ledger.get(id);
2559
- if (ledgerRow !== void 0 && ledgerRow.stamp !== void 0 && stamp !== null && ledgerRow.stamp === stamp && (ledgerRow.foldVersion ?? 1) === 10 && ledgerRow.fingerprint === foldFingerprint) {
2590
+ if (ledgerRow !== void 0 && ledgerRow.stamp !== void 0 && stamp !== null && ledgerRow.stamp === stamp && (ledgerRow.foldVersion ?? 1) === 11 && ledgerRow.fingerprint === foldFingerprint) {
2560
2591
  const fold = deserializeFold(ledgerRow.fold);
2561
2592
  folds.push({
2562
2593
  id,
@@ -2638,7 +2669,7 @@ function createUsageAggregator(persistence, options = {}) {
2638
2669
  for (const entry of ledger.values()) {
2639
2670
  if (included.has(entry.id)) continue;
2640
2671
  try {
2641
- const stale = (entry.foldVersion ?? 1) < 10 || entry.fingerprint !== foldFingerprint;
2672
+ const stale = (entry.foldVersion ?? 1) < 11 || entry.fingerprint !== foldFingerprint;
2642
2673
  folds.push({
2643
2674
  id: entry.id,
2644
2675
  ...entry.cwd === void 0 ? {} : { cwd: entry.cwd },
@@ -478,7 +478,7 @@ export interface UsageLedgerDocument {
478
478
  * 会话费用只剩最近一段,issue #29)。
479
479
  * 持久账本行据此区分新旧算法:日志已删/不可读而只能沿用旧行时,UI 标注置信度提示。
480
480
  */
481
- export declare const FOLD_VERSION = 10;
481
+ export declare const FOLD_VERSION = 11;
482
482
  /**
483
483
  * 一次性账本迁移:id 唯一,apply 在加载边界对原始文档执行,已应用过的跳过。
484
484
  * 未来账本/schema 字段变更(重命名、拆桶、语义调整)时,在此追加一条迁移并
@@ -126,6 +126,10 @@ interface SessionBillingRow {
126
126
  calls: number;
127
127
  cost: number;
128
128
  lastActive: number;
129
+ /** 展示层合并标记(issue #42):同标题会话归并后的段数(>1 时行尾显示 ×N)。 */
130
+ mergedCount?: number;
131
+ /** 合并组的段明细(展示层专用):一级行默认收起,展开后逐段显示。合并函数需 push,故非 readonly。 */
132
+ children?: SessionBillingRow[];
129
133
  }
130
134
  /** Usage stats structure from `.dsh-usage-stats.json`. */
131
135
  export interface UsageStats {
@@ -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' | 'trend' | 'trend7d' | 'trend30d' | 'trendMetric' | 'trendMetricCost' | 'trendMetricTokens' | 'trendEmpty' | 'budget' | 'budgetAmount' | 'budgetSummary' | 'sessions' | 'sessionTitle' | 'lastActive' | 'sessionOverflow' | 'budgetTierBody' | 'models' | 'providerBilling' | 'channelUnknown' | 'actual' | 'pricing' | 'input' | 'output' | 'cacheHit' | 'peak' | 'offPeak' | 'flat' | 'band' | 'close' | 'footer' | 'footerCredit' | 'lastUpdated' | 'noData' | 'todayRate' | 'rateLive' | 'rateBuiltin' | 'promoBadge' | 'promoUntil' | 'promoOpenEnded' | 'pricingTip' | 'pricingUnit' | 'pricingNotes' | 'ubPeak' | 'ubOff' | 'ubStd' | 'peakBand' | 'pricingSource' | 'noteCache' | 'noteBand' | 'noteSource' | 'balance' | 'balanceUnconfigured' | 'balanceUnauthorized' | 'balanceUnreachable' | 'uncatalogued' | 'estimatedPricing' | 'balanceDays' | 'balanceLowBody' | 'reconcileDrift' | 'reconcileDismiss' | 'subscriptionNotConfigured' | 'subscriptionUnauthorized' | 'subscriptionUnavailable' | 'subscriptionInvalid' | 'subscriptionRateLimited' | 'subscriptionSession' | 'subscriptionWeekly' | 'subscriptionMonthly' | 'subscriptionBilling' | 'subscriptionRemaining' | 'subscriptionExhausted' | 'subscriptionReset' | 'subscriptionNoApi' | 'floatWindow' | 'floatModeCombined' | 'floatModeSubscription' | 'floatMode' | 'floatTargets' | 'floatWindowHint' | 'floatNoTargets' | 'floatNoTargetsHint' | 'cardDisplay' | 'cardDisplayHint' | 'cardMetric' | 'cardMetricMoney' | 'cardMetricTokens' | 'triggerMonthTokens' | 'subscriptionsStale' | 'staleLedgerNotice' | 'tokenCacheWrite' | 'toolRank' | 'toolName' | 'userPrices' | 'userPricesHint' | 'userPriceSave' | 'userPriceModel' | 'userPriceSource' | 'userPriceSourceHint' | 'userPriceOffPeak' | 'userPriceNormal' | 'userPriceCurrency' | 'userPriceAdd' | 'userPriceRemoveSelected' | 'userPriceSelect' | 'sessionStaleBadge' | 'heatmapLess' | 'heatmapMore' | 'currency' | 'currencyCny' | 'currencyUsd' | 'heatmap' | 'rounds' | 'roundsHint' | 'anomaly' | 'workspaceSubtotal' | 'model' | 'thModel' | 'thInputMiss' | 'thInputHit' | 'costAbbr' | 'tabOverview' | 'tabTrends' | 'tabProviders' | 'tabPricing' | 'tabSettings' | 'budgetHint' | 'peakAlertHint' | 'peakAlertDescPeak' | 'peakAlertDescOff' | 'export' | 'exportCsvDay' | 'exportCsvSession' | 'exportJson' | 'peakShare' | 'peakSharePerCall' | 'offPeakSavings' | 'perfMax' | 'weekCost' | 'roleCost' | 'roleUser' | 'roleAssistant' | 'roleTool' | 'roleHint' | 'tierPeak' | 'tierOff' | 'tierToPeak' | 'tierToOff' | 'tierAlertEnterPeak' | 'tierAlertEnterOff' | 'peakAlertTitlePeak' | 'peakAlertTitleOff' | 'peakAlert' | 'peakAlertLeadMin' | 'peakAlertPos' | 'peakAlertMode' | 'peakAlertPosCorner' | 'peakAlertPosCenter' | 'peakAlertModePeak' | 'peakAlertModeOff' | 'peakAlertModeBoth' | 'peakAlertWebNotify' | 'peakAlertPreview' | 'planTypeCode' | 'planTypeToken' | 'subscriptionFeePerMonth' | 'triggerToday' | 'triggerMonth' | 'subscriptionIncluded' | 'free' | 'official' | 'thirdParty' | 'perfSamples' | 'perfTtft' | 'perfP50' | 'perfP90' | 'perfTps' | 'perfLatency' | 'perfEstimated' | 'perfEmpty' | 'perfTpsUnit' | 'perfTitle' | 'perfHint' | 'perfAll' | 'perfChartEmpty' | 'heatmapYear' | 'heatmapMonth' | 'activeDays' | 'streakDays' | 'subscriptionAutoDetect' | 'pluginAuthor' | 'pluginRepository' | 'pluginNpm' | 'pluginLicense' | 'tabToken' | 'tokenExport' | 'tokenExportCsv' | 'tokenCacheHitRate' | 'tokenReasoningShare' | 'tokenReasoningShort' | 'tokenIo' | 'tokenPeak' | 'tokenDaily' | 'tokenByModel' | 'tokenMiss' | 'tokenHit' | 'tokenOutput' | 'tokenViewStructure' | 'tokenViewModel' | 'tokenHitShort' | 'tokenMissShort' | 'tokenTotal' | 'tokenShare' | 'usageStatsTool' | 'usageStatsToolHint' | 'balanceGranted' | 'balanceTopped' | 'balanceDaily' | 'balanceDaysLong' | 'balanceDaysUnit' | 'popTodayModel' | 'popNoConsumption' | 'popTitle' | 'popDirectLead' | 'popSubLead' | 'unpricedHint' | 'searchEstimateHint' | 'siteListDisplay' | 'siteListDisplayHint' | 'liveCostBar' | 'liveCostBarHint' | 'liveCostBarPosition' | 'liveCostBarPosBelow' | 'liveCostBarPosAbove' | 'liveCostBarPosToolbar' | 'exportCsvSite' | 'panelRelayQuota' | 'relayBalance' | 'relayNoQuota' | 'relayWindowUsed' | 'relayKindNewApi' | 'relayKindSub2Api' | 'relayKindUnknown';
2
+ export type UsageBillingKey = 'title' | 'cost' | 'todayCost' | 'monthCost' | 'yearCost' | 'monthProjected' | 'liveTurn' | 'liveSession' | 'calls' | 'cacheHitRate' | 'tokens' | 'inputTokens' | 'outputTokens' | 'avgCost' | 'trend' | 'trend7d' | 'trend30d' | 'trendMetric' | 'trendMetricCost' | 'trendMetricTokens' | 'trendEmpty' | 'budget' | 'budgetAmount' | 'budgetSummary' | 'sessions' | 'sessionTitle' | 'lastActive' | 'sessionOverflow' | 'budgetTierBody' | 'models' | 'providerBilling' | 'channelUnknown' | 'actual' | 'pricing' | 'input' | 'output' | 'cacheHit' | 'peak' | 'offPeak' | 'flat' | 'band' | 'close' | 'footer' | 'footerCredit' | 'lastUpdated' | 'noData' | 'todayRate' | 'rateLive' | 'rateBuiltin' | 'promoBadge' | 'promoUntil' | 'promoOpenEnded' | 'pricingTip' | 'pricingUnit' | 'pricingNotes' | 'ubPeak' | 'ubOff' | 'ubStd' | 'peakBand' | 'pricingSource' | 'noteCache' | 'noteBand' | 'noteSource' | 'balance' | 'balanceUnconfigured' | 'balanceUnauthorized' | 'balanceUnreachable' | 'uncatalogued' | 'estimatedPricing' | 'balanceDays' | 'balanceLowBody' | 'reconcileDrift' | 'reconcileDismiss' | 'subscriptionNotConfigured' | 'subscriptionUnauthorized' | 'subscriptionUnavailable' | 'subscriptionInvalid' | 'subscriptionRateLimited' | 'subscriptionSession' | 'subscriptionWeekly' | 'subscriptionMonthly' | 'subscriptionBilling' | 'subscriptionRemaining' | 'subscriptionExhausted' | 'subscriptionReset' | 'subscriptionNoApi' | 'floatWindow' | 'floatModeCombined' | 'floatModeSubscription' | 'floatMode' | 'floatTargets' | 'floatWindowHint' | 'floatNoTargets' | 'floatNoTargetsHint' | 'cardDisplay' | 'cardDisplayHint' | 'cardMetric' | 'cardMetricMoney' | 'cardMetricTokens' | 'triggerMonthTokens' | 'subscriptionsStale' | 'staleLedgerNotice' | 'tokenCacheWrite' | 'toolRank' | 'toolName' | 'userPrices' | 'userPricesHint' | 'userPriceSave' | 'userPriceModel' | 'userPriceSource' | 'userPriceSourceHint' | 'userPriceOffPeak' | 'userPriceNormal' | 'userPriceCurrency' | 'userPriceAdd' | 'userPriceRemoveSelected' | 'userPriceSelect' | 'sessionStaleBadge' | 'sessionUntitled' | 'heatmapLess' | 'heatmapMore' | 'currency' | 'currencyCny' | 'currencyUsd' | 'heatmap' | 'rounds' | 'roundsHint' | 'anomaly' | 'model' | 'thModel' | 'thInputMiss' | 'thInputHit' | 'costAbbr' | 'tabOverview' | 'tabTrends' | 'tabProviders' | 'tabPricing' | 'tabSettings' | 'budgetHint' | 'peakAlertHint' | 'peakAlertDescPeak' | 'peakAlertDescOff' | 'export' | 'exportCsvDay' | 'exportCsvSession' | 'exportJson' | 'peakShare' | 'peakSharePerCall' | 'offPeakSavings' | 'perfMax' | 'weekCost' | 'roleCost' | 'roleUser' | 'roleAssistant' | 'roleTool' | 'roleHint' | 'tierPeak' | 'tierOff' | 'tierToPeak' | 'tierToOff' | 'tierAlertEnterPeak' | 'tierAlertEnterOff' | 'peakAlertTitlePeak' | 'peakAlertTitleOff' | 'peakAlert' | 'peakAlertLeadMin' | 'peakAlertPos' | 'peakAlertMode' | 'peakAlertPosCorner' | 'peakAlertPosCenter' | 'peakAlertModePeak' | 'peakAlertModeOff' | 'peakAlertModeBoth' | 'peakAlertWebNotify' | 'peakAlertPreview' | 'planTypeCode' | 'planTypeToken' | 'subscriptionFeePerMonth' | 'triggerToday' | 'triggerMonth' | 'subscriptionIncluded' | 'free' | 'official' | 'thirdParty' | 'perfSamples' | 'perfTtft' | 'perfP50' | 'perfP90' | 'perfTps' | 'perfLatency' | 'perfEstimated' | 'perfEmpty' | 'perfTpsUnit' | 'perfTitle' | 'perfHint' | 'perfAll' | 'perfChartEmpty' | 'heatmapYear' | 'heatmapMonth' | 'activeDays' | 'streakDays' | 'subscriptionAutoDetect' | 'pluginAuthor' | 'pluginRepository' | 'pluginNpm' | 'pluginLicense' | 'tabToken' | 'tokenExport' | 'tokenExportCsv' | 'tokenCacheHitRate' | 'tokenReasoningShare' | 'tokenReasoningShort' | 'tokenIo' | 'tokenPeak' | 'tokenDaily' | 'tokenByModel' | 'tokenMiss' | 'tokenHit' | 'tokenOutput' | 'tokenViewStructure' | 'tokenViewModel' | 'tokenHitShort' | 'tokenMissShort' | 'tokenTotal' | 'tokenShare' | 'usageStatsTool' | 'usageStatsToolHint' | 'balanceGranted' | 'balanceTopped' | 'balanceDaily' | 'balanceDaysLong' | 'balanceDaysUnit' | 'popTodayModel' | 'popNoConsumption' | 'popTitle' | 'popDirectLead' | 'popSubLead' | 'unpricedHint' | 'searchEstimateHint' | 'siteListDisplay' | 'siteListDisplayHint' | 'liveCostBar' | 'liveCostBarHint' | 'liveCostBarPosition' | 'liveCostBarPosBelow' | 'liveCostBarPosAbove' | 'liveCostBarPosToolbar' | 'exportCsvSite' | 'panelRelayQuota' | 'relayBalance' | 'relayNoQuota' | 'relayWindowUsed' | 'relayKindNewApi' | 'relayKindSub2Api' | 'relayKindUnknown';
3
3
  export declare const NS = "usageBilling";
4
4
  export declare const zh: Record<UsageBillingKey, string>;
5
5
  export declare const en: Record<UsageBillingKey, string>;
@@ -153,6 +153,14 @@ export declare const PEAK_ERA_START_MS: number;
153
153
  * 档位判定按事件所在时段适用各自的规则,不得统一套现行规则重算历史。
154
154
  */
155
155
  export declare const WEEKEND_OFFPEAK_START_MS: number;
156
+ /**
157
+ * flash 系调价分界(UTC 2026-09-10T04:00:00Z,即北京时间 2026-09-10 12:00):
158
+ * 官方自此刻起 V4 Flash / V4 Flash Vision (Exp) 调价——谷档 1.5/0.05/4.5 →
159
+ * 1/0.02/4(峰 = 谷 × 2)。目录条目写现行(新)价;分界前的历史事件由
160
+ * {@link computeCostAt} 按 {@link FLASH_REPRICED_OFFPEAK} 回算旧价,与
161
+ * {@link PEAK_ERA_START_MS} 同一「按事件时刻分段适用规则」口径。
162
+ */
163
+ export declare const FLASH_REPRICE_MS: number;
156
164
  /** 计费时段档位:高峰 / 空闲(官方 DeepSeek 刊例价:高峰 = 空闲 × 2)。 */
157
165
  export type PriceTierId = 'peak' | 'offPeak';
158
166
  /** 成本显示币种:人民币(国内模型直价)/ 美元(国外模型直价或换算显示)。 */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kenz1117/dsh-ui-usage-billing",
3
3
  "description": "Usage billing dashboard for DeepSeek Harness: sidebar cost metrics plus a full dashboard modal, priced from a current multi-provider catalog with real usage aggregated from session logs.",
4
- "version": "1.0.41",
4
+ "version": "1.0.43",
5
5
  "keywords": [
6
6
  "deepseek-harness",
7
7
  "deepseek",
@@ -72,7 +72,8 @@
72
72
  },
73
73
  "license": "MIT",
74
74
  "engines": {
75
- "node": "^22.19.0 || >=24.0.0"
75
+ "node": "^22.19.0 || >=24.0.0",
76
+ "dsh": ">=0.1.2-alpha.1"
76
77
  },
77
78
  "peerDependencies": {
78
79
  "@deepseek-ai/cordis": "*",