@kenz1117/dsh-ui-usage-billing 1.8.0 → 1.8.1-alpha.2

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
@@ -9482,7 +9482,7 @@ var TaskQueueEngine = class {
9482
9482
  this.heartbeat = void 0;
9483
9483
  this.taskAbort?.abort();
9484
9484
  }
9485
- async snapshot() {
9485
+ async snapshot(refreshModels = false) {
9486
9486
  const countdown = channelCountdown(this.now(), "deepseek-metered");
9487
9487
  const controller = usableController(this.options.getController());
9488
9488
  const base = {
@@ -9499,7 +9499,7 @@ var TaskQueueEngine = class {
9499
9499
  try {
9500
9500
  return {
9501
9501
  ...base,
9502
- models: await this.modelOptions(controller)
9502
+ ...await this.modelOptions(controller, refreshModels)
9503
9503
  };
9504
9504
  } catch (error) {
9505
9505
  return {
@@ -9529,7 +9529,7 @@ var TaskQueueEngine = class {
9529
9529
  if (!Array.isArray(inputs) || inputs.length === 0) throw new TaskQueueError("at least one task is required");
9530
9530
  if (inputs.length > MAX_QUEUED) throw new TaskQueueError("too many active queue items", 409);
9531
9531
  const workspaces = this.options.getWorkspaces();
9532
- const models = await this.modelOptions(controller, true);
9532
+ const { models } = await this.modelOptions(controller, true);
9533
9533
  const validated = inputs.map((input, index) => {
9534
9534
  try {
9535
9535
  if (input === null || typeof input !== "object" || Array.isArray(input)) throw new TaskQueueError("task must be a JSON object");
@@ -9578,7 +9578,7 @@ var TaskQueueEngine = class {
9578
9578
  });
9579
9579
  }
9580
9580
  async modelOptions(controller, refresh = false) {
9581
- if (!refresh && this.modelCache !== void 0 && this.now() - this.modelCache.at < OPTIONS_CACHE_MS) return this.modelCache.models;
9581
+ if (!refresh && this.modelCache !== void 0 && this.now() - this.modelCache.at < OPTIONS_CACHE_MS) return this.modelCache;
9582
9582
  const catalog = await controller.modelCatalog();
9583
9583
  const models = [];
9584
9584
  for (const group of catalog.groups) {
@@ -9593,11 +9593,20 @@ var TaskQueueEngine = class {
9593
9593
  });
9594
9594
  }
9595
9595
  }
9596
+ const candidate = catalog.default;
9597
+ const defaultModel = candidate === void 0 ? void 0 : {
9598
+ provider: candidate.provider,
9599
+ model: candidate.model
9600
+ };
9596
9601
  this.modelCache = {
9597
9602
  at: this.now(),
9598
- models
9603
+ models,
9604
+ defaultModel
9605
+ };
9606
+ return {
9607
+ models,
9608
+ defaultModel
9599
9609
  };
9600
- return models;
9601
9610
  }
9602
9611
  async pump() {
9603
9612
  if (this.stopped || this.pumping) return;
@@ -9670,7 +9679,8 @@ var TaskQueueEngine = class {
9670
9679
  await this.requeue(claimed.id);
9671
9680
  return;
9672
9681
  }
9673
- if (!(await this.modelOptions(controller, true)).some((model) => model.provider === claimed.provider && model.id === claimed.model)) throw new TaskQueueError("the selected official DeepSeek model is no longer available", 409);
9682
+ const { models: availableModels } = await this.modelOptions(controller, true);
9683
+ if (!availableModels.some((model) => model.provider === claimed.provider && model.id === claimed.model)) throw new TaskQueueError("the selected official DeepSeek model is no longer available", 409);
9674
9684
  const { sessionId } = await controller.create({ cwd: claimed.cwd });
9675
9685
  if (!await this.patch(claimed.id, { sessionId })) return;
9676
9686
  await controller.selectModel({
@@ -9866,7 +9876,8 @@ function registerTaskQueueRoute(ctx, deps) {
9866
9876
  }
9867
9877
  try {
9868
9878
  if (req.method === "GET") {
9869
- send(res, 200, await deps.engine.snapshot());
9879
+ const refresh = new URL(req.url ?? "", "http://127.0.0.1").searchParams.get("refresh") === "1";
9880
+ send(res, 200, await deps.engine.snapshot(refresh));
9870
9881
  return;
9871
9882
  }
9872
9883
  const chunks = [];
@@ -1,6 +1,6 @@
1
1
  /** API client for the new-host off-peak task queue preview (issue #106). */
2
2
  import type { TaskQueueInput, TaskQueueSnapshot, TaskQueueSummary } from '../../task-queue-shared.ts';
3
- export declare function loadTaskQueue(): Promise<TaskQueueSnapshot>;
3
+ export declare function loadTaskQueue(refreshModels?: boolean): Promise<TaskQueueSnapshot>;
4
4
  export declare function loadTaskQueueSummary(): Promise<TaskQueueSummary>;
5
5
  export type TaskQueueAction = {
6
6
  action: 'enqueue';
@@ -38,8 +38,8 @@ export declare const DASHBOARD_TABS: readonly {
38
38
  id: DashboardTab;
39
39
  labelKey: UsageBillingKey;
40
40
  }[];
41
- /** 平均成本的统计范围(issue #47);`all` = 全量累计,不进逐日求和。 */
42
- export type AvgCostRange = 'today' | '7d' | 'week' | 'month' | 'all';
41
+ /** Hero + KPI 统计范围;`all` 用总量,`custom` 用持久化的本地起止日期。 */
42
+ export type AvgCostRange = 'today' | '7d' | 'week' | 'month' | 'all' | 'custom';
43
43
  /** 全局 KPI 按日聚合行的最小字段(byDay 行 = ModelUsage,结构兼容)。 */
44
44
  export interface KpiDayRow {
45
45
  cost: number;
@@ -48,6 +48,7 @@ export interface KpiDayRow {
48
48
  output: number;
49
49
  cacheHit: number;
50
50
  cacheMiss: number;
51
+ cacheWrite?: number;
51
52
  reasoning?: number;
52
53
  }
53
54
  /** 全局 KPI 聚合结果:KPI 七卡按所选范围重算所需的全部字段。 */
@@ -58,6 +59,7 @@ export interface KpiAgg {
58
59
  output: number;
59
60
  cacheHit: number;
60
61
  cacheMiss: number;
62
+ cacheWrite: number;
61
63
  reasoning: number;
62
64
  /** 范围内总处理 Token(缓存读+缓存写+输出)最大的日期戳;窗口无数据时 undefined。 */
63
65
  peakDay: string | undefined;
@@ -31,5 +31,7 @@ export declare function sinceMondayOf<T>(byDay: Record<string, T>, today: string
31
31
  * 本月。日期戳字典序即时间序(与 dailyBurnRate 同口径);累计口径由调用方
32
32
  * 直接取 total(含搜索估值兜底),不走此函数。
33
33
  */
34
- export declare function sumByDayRange(byDay: Record<string, KpiDayRow>, today: string, range: Exclude<AvgCostRange, 'all'>): KpiAgg;
34
+ export declare function sumByDayRange(byDay: Record<string, KpiDayRow>, today: string, range: Exclude<AvgCostRange, 'all' | 'custom'>): KpiAgg;
35
+ /** 自定义本地日期范围:起止日均完整包含,字典序边界与 byDay 键一致。 */
36
+ export declare function sumByDayCustomRange(byDay: Record<string, KpiDayRow>, start: string, end: string): KpiAgg;
35
37
  //# sourceMappingURL=week.d.ts.map
@@ -1,5 +1,5 @@
1
1
  /** Locale dictionaries for the usage billing surface. */
2
- export type UsageBillingKey = 'title' | 'cost' | 'todayCost' | 'monthCost' | 'yearCost' | 'monthProjected' | 'monthProjectedHint' | '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' | 'balanceStaleNotice' | 'staleLedgerNotice' | 'staleSnapshotNotice' | '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' | 'peakAlertQueuePeak' | 'peakAlertQueueOff' | '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' | 'settingsNavDisplayPref' | 'settingsNavBudget' | 'settingsNavAlert' | 'settingsNavDisplay' | 'settingsNavAdvanced' | 'settingsNavAbout' | 'settingsSearchPlaceholder' | 'settingsSearchEmpty' | 'sessionsViewAll' | 'sessionViewerSearch' | 'modelBudgetTitle' | 'modelBudgetHint' | 'modelBudgetBody' | 'modelBudgetPlaceholder' | 'moreWorksTitle' | 'adEngramName' | 'adEngramDesc' | 'adRainbowName' | 'adRainbowDesc' | 'kpiDescCacheHit' | 'kpiDescTokens' | 'kpiDescAvgCost' | 'kpiDescCalls' | 'kpiDescReasoning' | 'kpiDescIo' | 'kpiDescPeak' | 'healthDotLive' | 'healthDotFailed' | 'healthDotUnknown' | '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' | 'commandUsageLabel' | 'commandUsageDescription' | 'sessionOpen' | 'sessionOpenFailed' | 'sessionOpenUnavailable' | 'tabAgents' | 'tabQueue' | 'queueSubtitle' | 'queueUntilPeak' | 'queueUntilOffPeak' | 'queueUnsupportedTitle' | 'queueUnsupportedBody' | 'queueSafety' | 'queueWorkspace' | 'queueModel' | 'queueNoOptions' | 'queuePromptLabel' | 'queuePromptPlaceholder' | 'queuePrivacy' | 'queueEnqueue' | 'queueImport' | 'queueImportHint' | 'queueImported' | 'queueImportFormat' | 'queueImportTooLarge' | 'queueActive' | 'queueClearFinished' | 'queueEmpty' | 'queueLoading' | 'queueOpenSession' | 'queueRemoveQueued' | 'queueRemoveHistory' | 'queueStatusQueued' | 'queueStatusStarting' | 'queueStatusRunning' | 'queueStatusCompleted' | 'queueStatusFailed' | 'agentsSummary' | 'agentsCount' | 'agentsDelegations' | 'agentsRoots' | 'agentsMostExpensive' | 'agentsChainTotal' | 'agentsNoData' | 'agentsSubagent' | 'agentsRoot';
2
+ export type UsageBillingKey = 'title' | 'cost' | 'todayCost' | 'monthCost' | 'yearCost' | 'monthProjected' | 'monthProjectedHint' | 'liveTurn' | 'liveSession' | 'liveSessionSub' | 'calls' | 'cacheHitRate' | 'tokens' | 'inputTokens' | 'outputTokens' | 'avgCost' | 'kpiRange' | 'avgRangeToday' | 'avgRange7d' | 'avgRangeWeek' | 'avgRangeMonth' | 'avgRangeAll' | 'avgRangeCustom' | 'customRangeStart' | 'customRangeEnd' | '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' | 'balanceStaleNotice' | 'staleLedgerNotice' | 'staleSnapshotNotice' | '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' | 'peakAlertQueuePeak' | 'peakAlertQueueOff' | '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' | 'settingsNavDisplayPref' | 'settingsNavBudget' | 'settingsNavAlert' | 'settingsNavDisplay' | 'settingsNavAdvanced' | 'settingsNavAbout' | 'settingsSearchPlaceholder' | 'settingsSearchEmpty' | 'sessionsViewAll' | 'sessionViewerSearch' | 'modelBudgetTitle' | 'modelBudgetHint' | 'modelBudgetBody' | 'modelBudgetPlaceholder' | 'moreWorksTitle' | 'adEngramName' | 'adEngramDesc' | 'adRainbowName' | 'adRainbowDesc' | 'kpiDescCacheHit' | 'kpiDescTokens' | 'kpiDescAvgCost' | 'kpiDescCalls' | 'kpiDescReasoning' | 'kpiDescIo' | 'kpiDescPeak' | 'healthDotLive' | 'healthDotFailed' | 'healthDotUnknown' | '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' | 'commandUsageLabel' | 'commandUsageDescription' | 'sessionOpen' | 'sessionOpenFailed' | 'sessionOpenUnavailable' | 'tabAgents' | 'tabQueue' | 'queueSubtitle' | 'queueUntilPeak' | 'queueUntilOffPeak' | 'queueUnsupportedTitle' | 'queueUnsupportedBody' | 'queueSafety' | 'queueWorkspace' | 'queueModel' | 'queueNoOptions' | 'queuePromptLabel' | 'queuePromptPlaceholder' | 'queuePrivacy' | 'queueEnqueue' | 'queueImport' | 'queueImportHint' | 'queueImported' | 'queueImportFormat' | 'queueImportTooLarge' | 'queueActive' | 'queueClearFinished' | 'queueEmpty' | 'queueLoading' | 'queueOpenSession' | 'queueRemoveQueued' | 'queueRemoveHistory' | 'queueStatusQueued' | 'queueStatusStarting' | 'queueStatusRunning' | 'queueStatusCompleted' | 'queueStatusFailed' | 'quickQueueToggle' | 'quickQueueEnqueue' | 'quickQueueEnqueueing' | 'quickQueueWaiting' | 'quickQueueClear' | 'quickQueueEnqueued' | 'quickQueueEmpty' | 'quickQueueBusy' | 'quickQueueAttachments' | 'quickQueueContext' | 'quickQueueRoute' | 'quickQueueDraftChanged' | 'quickQueueUnsupported' | 'quickQueueFailed' | 'agentsSummary' | 'agentsCount' | 'agentsDelegations' | 'agentsRoots' | 'agentsMostExpensive' | 'agentsChainTotal' | 'agentsNoData' | 'agentsSubagent' | 'agentsRoot';
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>;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Composer shortcut for the existing off-peak task queue.
3
+ *
4
+ * This component only snapshots the current draft, working directory and next
5
+ * model route into the queue API. It never submits to the current Session and
6
+ * never starts a task. Optional draft clearing is revision-checked after the
7
+ * mutation succeeds so late responses cannot erase subsequent user input.
8
+ */
9
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
10
+ import type { InputActions, InputState } from '@deepseek-ai/dsh-client-ui-conversation/client';
11
+ import type { ObservableSnapshot } from '@deepseek-ai/dsh-client-store';
12
+ import type { SessionProjectionMap } from '@deepseek-ai/dsh-api-session-controller/client';
13
+ import type { UsageBillingKey } from './locales.ts';
14
+ type Translate = (key: UsageBillingKey) => string;
15
+ type ProjectionKey = Extract<keyof SessionProjectionMap, string>;
16
+ /** Optional selector shape: old hosts may omit the standard input kit. */
17
+ type ReadInput = <S>(selector: (state: InputState) => S, eq?: (a: S, b: S) => boolean) => S | undefined;
18
+ /**
19
+ * Projection cells come from the current Session's public `projections.faceOf`.
20
+ * The composer standard kit guarantees `useInput`; projection access remains an
21
+ * optional capability so older hosts degrade instead of blocking web startup.
22
+ */
23
+ export type ProjectionFaceOf = (key: ProjectionKey) => ObservableSnapshot<unknown> | undefined;
24
+ export interface QuickQueueToggleProps {
25
+ readonly t: Translate;
26
+ }
27
+ export interface QuickQueueEnqueueProps {
28
+ readonly sessionId: SessionId;
29
+ readonly t: Translate;
30
+ readonly useInput?: ReadInput | undefined;
31
+ readonly inputActions?: InputActions | undefined;
32
+ readonly projectionFaceOf?: ProjectionFaceOf | undefined;
33
+ }
34
+ /** Persistent, opt-in composer switch. It performs no queue or network writes. */
35
+ export declare function QuickQueueToggle({ t }: QuickQueueToggleProps): React.ReactNode;
36
+ /** Enqueue the captured draft for a later off-peak window; never prompt the current Session. */
37
+ export declare function QuickQueueEnqueue({ sessionId, t, useInput, inputActions, projectionFaceOf, }: QuickQueueEnqueueProps): React.ReactNode;
38
+ export {};
39
+ //# sourceMappingURL=task-queue-quick.d.ts.map
@@ -65,14 +65,24 @@ export declare const BILLING_CARD_STORAGE_KEY = "dsh.ui-usage-billing.card";
65
65
  export declare function loadBillingCardPrefs(): BillingCardPrefs;
66
66
  /** 写入计费卡偏好。失败静默(展示偏好非关键)。 */
67
67
  export declare function saveBillingCardPrefs(prefs: BillingCardPrefs): void;
68
- /** 概览 KPI 全局统计范围(今日/近7天/本周/本月/累计),与组件内 AvgCostRange 同构。 */
69
- export type KpiRangePref = 'today' | '7d' | 'week' | 'month' | 'all';
68
+ /** 概览 Hero + KPI 全局统计范围(预设或自定义起止日期),与组件内 AvgCostRange 同构。 */
69
+ export type KpiRangePref = 'today' | '7d' | 'week' | 'month' | 'all' | 'custom';
70
+ /** 自定义日期范围:本地日历日,起止均包含;不伪装成分钟级切片。 */
71
+ export interface KpiCustomRange {
72
+ start: string;
73
+ end: string;
74
+ }
70
75
  /** localStorage key(与其他 `dsh.ui-usage-billing.*` 偏好同命名空间)。 */
71
76
  export declare const KPI_RANGE_STORAGE_KEY = "dsh.ui-usage-billing.kpi-range";
77
+ export declare const KPI_CUSTOM_RANGE_STORAGE_KEY = "dsh.ui-usage-billing.kpi-custom-range";
72
78
  /** 读取 KPI 全局范围偏好(损坏/越界回退「累计」)。仅在浏览器半区调用。 */
73
79
  export declare function loadKpiRange(): KpiRangePref;
74
80
  /** 写入 KPI 全局范围偏好。失败静默(展示偏好非关键)。 */
75
81
  export declare function saveKpiRange(range: KpiRangePref): void;
82
+ /** 自定义范围缺省为昨天;损坏、非法日期或起止倒置一律回退,避免意外全量。 */
83
+ export declare function loadKpiCustomRange(): KpiCustomRange;
84
+ /** 自定义起止日期与范围种类分开保存,切走再切回仍保留上次选择。 */
85
+ export declare function saveKpiCustomRange(range: KpiCustomRange): void;
76
86
  /**
77
87
  * 中转站列表(中转站分布 / 中转站额度)的展示偏好(issue #17)。
78
88
  * 纯 client 偏好,存 localStorage(不依赖 node 半区接口/设置 schema)。
@@ -245,4 +255,18 @@ export declare const DEFAULT_MOTION: MotionPref;
245
255
  export declare function loadMotion(): MotionPref;
246
256
  /** 写入动效偏好并同步派发事件。失败静默。 */
247
257
  export declare function saveMotion(motion: MotionPref): void;
258
+ /** Composer shortcut preferences; both actions are opt-in and default off. */
259
+ export interface QuickQueuePrefs {
260
+ /** Show the draft enqueue controls beside the composer. */
261
+ enabled: boolean;
262
+ /** Clear only the exact enqueued draft revision after a successful mutation. */
263
+ clearAfterEnqueue: boolean;
264
+ }
265
+ export declare const DEFAULT_QUICK_QUEUE_PREFS: QuickQueuePrefs;
266
+ export declare const QUICK_QUEUE_STORAGE_KEY = "dsh.ui-usage-billing.quick-queue";
267
+ export declare const QUICK_QUEUE_PREF_EVENT = "dsh.ui-usage-billing.quick-queue-pref";
268
+ /** Read composer queue preferences, failing closed on missing or malformed values. */
269
+ export declare function loadQuickQueuePrefs(): QuickQueuePrefs;
270
+ /** Persist and broadcast to the independent left/right composer React trees. */
271
+ export declare function saveQuickQueuePrefs(prefs: QuickQueuePrefs): void;
248
272
  //# sourceMappingURL=usage-billing-settings.d.ts.map
@@ -28,11 +28,11 @@ export interface VolatileToggle {
28
28
  * object 透传未声明键,其余 config 字段不受影响;未导出 Config 的旧宿主直接
29
29
  * 把原始 config 交给 apply,普通布尔形态由读取端兼容。
30
30
  */
31
- export declare const Config: z<Schemastery.ObjectS<NoInfer<{
32
- enableUsageStatsTool: z<boolean, boolean, "volatile-defined">;
33
- }>>, Schemastery.ObjectT<NoInfer<{
34
- enableUsageStatsTool: z<boolean, boolean, "volatile-defined">;
35
- }>>, "plain">;
31
+ export declare const Config: z<{
32
+ enableUsageStatsTool?: boolean | null;
33
+ }, {
34
+ enableUsageStatsTool: VolatileToggle;
35
+ }>;
36
36
  /** Plugin configuration. */
37
37
  export interface UsageBillingConfig {
38
38
  /** Absolute path to a `.dsh-usage-stats.json` fallback file. */
@@ -30,6 +30,10 @@ export interface TaskQueueModel {
30
30
  readonly id: string;
31
31
  readonly name: string;
32
32
  }
33
+ export interface TaskQueueModelSelection {
34
+ readonly provider: string;
35
+ readonly model: string;
36
+ }
33
37
  export interface TaskQueueSnapshot {
34
38
  /** All required host Session-control methods are available. */
35
39
  readonly supported: boolean;
@@ -38,6 +42,8 @@ export interface TaskQueueSnapshot {
38
42
  readonly tasks: readonly TaskQueueTask[];
39
43
  readonly workspaces: readonly TaskQueueWorkspace[];
40
44
  readonly models: readonly TaskQueueModel[];
45
+ /** Host default route for an unconfigured Session; eligibility is checked separately. */
46
+ readonly defaultModel?: TaskQueueModelSelection | undefined;
41
47
  readonly optionsError?: string;
42
48
  }
43
49
  /** Lightweight alert polling shape: never transports Prompt or Session content. */
@@ -38,7 +38,7 @@ export declare class TaskQueueEngine {
38
38
  constructor(options: TaskQueueEngineOptions);
39
39
  start(): void;
40
40
  stop(): void;
41
- snapshot(): Promise<TaskQueueSnapshot>;
41
+ snapshot(refreshModels?: boolean): Promise<TaskQueueSnapshot>;
42
42
  summary(): Promise<TaskQueueSummary>;
43
43
  enqueue(input: TaskQueueInput): Promise<void>;
44
44
  /** Validate the whole batch before one locked append: no partially admitted import. */
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.8.0",
4
+ "version": "1.8.1-alpha.2",
5
5
  "keywords": [
6
6
  "deepseek-harness",
7
7
  "deepseek",