@kenz1117/dsh-ui-usage-billing 0.9.18 → 0.9.20

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/client.js CHANGED
@@ -31,18 +31,25 @@ window.__ModuleLoader__.load({
31
31
  };
32
32
  /** localStorage key(与 budget store 的 `dsh.ui-usage-billing.*` 命名空间一致)。 */
33
33
  const FLOAT_WINDOW_STORAGE_KEY = "dsh.ui-usage-billing.float";
34
- /** 读取浮窗偏好(含损坏/缺失回退到默认)。仅在浏览器半区调用。 */
34
+ /** 读取浮窗偏好(含损坏/缺失回退到默认)。仅在浏览器半区调用。
35
+ * 返回全新对象(含 targets 数组拷贝),避免调用方就地修改污染共享默认值。 */
35
36
  function loadFloatWindowPrefs() {
36
37
  try {
37
38
  const raw = localStorage.getItem(FLOAT_WINDOW_STORAGE_KEY);
38
- if (raw === null) return DEFAULT_FLOAT_WINDOW_PREFS;
39
+ if (raw === null) return {
40
+ ...DEFAULT_FLOAT_WINDOW_PREFS,
41
+ targets: [...DEFAULT_FLOAT_WINDOW_PREFS.targets]
42
+ };
39
43
  const parsed = JSON.parse(raw);
40
44
  return {
41
45
  mode: parsed.mode === "subscription" ? "subscription" : "combined",
42
46
  targets: Array.isArray(parsed.targets) ? parsed.targets.filter((entry) => typeof entry === "string") : []
43
47
  };
44
48
  } catch {
45
- return DEFAULT_FLOAT_WINDOW_PREFS;
49
+ return {
50
+ ...DEFAULT_FLOAT_WINDOW_PREFS,
51
+ targets: [...DEFAULT_FLOAT_WINDOW_PREFS.targets]
52
+ };
46
53
  }
47
54
  }
48
55
  /** 写入浮窗偏好。失败静默(展示偏好非关键)。 */
@@ -63,347 +70,347 @@ window.__ModuleLoader__.load({
63
70
  document.head.appendChild(tag);
64
71
  }
65
72
  var UsageBilling_module_css_default = {
66
- "kpiGreen": "VWh0dG_kpiGreen",
67
- "tokenModelBar": "VWh0dG_tokenModelBar",
68
- "peakAlertPeak": "VWh0dG_peakAlertPeak",
69
- "triggerPopMetricValue": "VWh0dG_triggerPopMetricValue",
70
- "switchOn": "VWh0dG_switchOn",
71
- "tabPanelIn": "VWh0dG_tabPanelIn",
72
- "subscriptionFillOver": "VWh0dG_subscriptionFillOver",
73
- "budgetHint": "VWh0dG_budgetHint",
74
- "triggerPopBadgeDirect": "VWh0dG_triggerPopBadgeDirect",
75
- "chartStack": "VWh0dG_chartStack",
76
- "roundsBarLabel": "VWh0dG_roundsBarLabel",
77
- "heatmapYearWeekday": "VWh0dG_heatmapYearWeekday",
78
- "healthOk": "VWh0dG_healthOk",
79
- "balanceDetailClose": "VWh0dG_balanceDetailClose",
80
- "shareSegAssistant": "VWh0dG_shareSegAssistant",
81
- "pricingTable": "VWh0dG_pricingTable",
82
- "unpricedHint": "VWh0dG_unpricedHint",
83
- "chartLegend": "VWh0dG_chartLegend",
84
- "budgetValue": "VWh0dG_budgetValue",
85
- "roundsBarColPeak": "VWh0dG_roundsBarColPeak",
86
- "subscriptionMeta": "VWh0dG_subscriptionMeta",
87
- "roundsFlagBadge": "VWh0dG_roundsFlagBadge",
73
+ "shareSegUser": "VWh0dG_shareSegUser",
74
+ "budgetFillWarn": "VWh0dG_budgetFillWarn",
75
+ "chartTooltipRow": "VWh0dG_chartTooltipRow",
76
+ "rateBadgeLive": "VWh0dG_rateBadgeLive",
77
+ "siteKindUnknown": "VWh0dG_siteKindUnknown",
78
+ "triggerSub": "VWh0dG_triggerSub",
79
+ "subscriptionFillWarn": "VWh0dG_subscriptionFillWarn",
80
+ "roundsFlagMark": "VWh0dG_roundsFlagMark",
81
+ "floatTargets": "VWh0dG_floatTargets",
82
+ "bucketStatLabel": "VWh0dG_bucketStatLabel",
83
+ "providerGroupName": "VWh0dG_providerGroupName",
84
+ "floatModeBtn": "VWh0dG_floatModeBtn",
85
+ "floatSub": "VWh0dG_floatSub",
86
+ "budgetFillOver": "VWh0dG_budgetFillOver",
88
87
  "numCol": "VWh0dG_numCol",
89
- "providerGroupBalanceLabel": "VWh0dG_providerGroupBalanceLabel",
90
- "triggerPopSwitchBtn": "VWh0dG_triggerPopSwitchBtn",
91
- "shareValue": "VWh0dG_shareValue",
92
- "trigger": "VWh0dG_trigger",
93
- "triggerPopMetricLabel": "VWh0dG_triggerPopMetricLabel",
94
- "dashboardTitle": "VWh0dG_dashboardTitle",
95
- "healthBad": "VWh0dG_healthBad",
96
- "subscriptionGrid": "VWh0dG_subscriptionGrid",
97
- "subscriptionWindowLabel": "VWh0dG_subscriptionWindowLabel",
98
- "balanceDays": "VWh0dG_balanceDays",
99
- "heatmap": "VWh0dG_heatmap",
100
- "heatmapYearMonths": "VWh0dG_heatmapYearMonths",
101
- "budget": "VWh0dG_budget",
102
- "chartLine": "VWh0dG_chartLine",
103
- "floatSubName": "VWh0dG_floatSubName",
104
- "bucketOfficial": "VWh0dG_bucketOfficial",
105
- "currencyButtonActive": "VWh0dG_currencyButtonActive",
106
- "heroSideLabel": "VWh0dG_heroSideLabel",
107
- "triggerSpark": "VWh0dG_triggerSpark",
108
- "siteRowCost": "VWh0dG_siteRowCost",
109
- "bandPrice": "VWh0dG_bandPrice",
110
- "tableScroll": "VWh0dG_tableScroll",
111
- "shareSegPeak": "VWh0dG_shareSegPeak",
112
- "bandTagOff": "VWh0dG_bandTagOff",
113
- "siteRowMeta": "VWh0dG_siteRowMeta",
114
- "railButton": "VWh0dG_railButton",
115
- "dashboardHead": "VWh0dG_dashboardHead",
116
- "subscriptionTrack": "VWh0dG_subscriptionTrack",
117
88
  "tokenModelPartOut": "VWh0dG_tokenModelPartOut",
118
- "heatmapHover": "VWh0dG_heatmapHover",
89
+ "rangeToggle": "VWh0dG_rangeToggle",
90
+ "peakAlertPreview": "VWh0dG_peakAlertPreview",
91
+ "chartStack": "VWh0dG_chartStack",
92
+ "triggerSparkHot": "VWh0dG_triggerSparkHot",
93
+ "budgetFill": "VWh0dG_budgetFill",
119
94
  "liveTierOff": "VWh0dG_liveTierOff",
120
- "floatTargets": "VWh0dG_floatTargets",
121
- "balanceDetailRow": "VWh0dG_balanceDetailRow",
122
- "flatTag": "VWh0dG_flatTag",
123
- "dashboardIn": "VWh0dG_dashboardIn",
124
- "tokenPanel": "VWh0dG_tokenPanel",
125
- "peakAlertPanelLabel": "VWh0dG_peakAlertPanelLabel",
126
- "triggerIcon": "VWh0dG_triggerIcon",
127
- "bucketStatSub": "VWh0dG_bucketStatSub",
128
- "shareSegTool": "VWh0dG_shareSegTool",
129
- "providerGroupMeta": "VWh0dG_providerGroupMeta",
130
- "heroGaugePctOver": "VWh0dG_heroGaugePctOver",
131
- "subscriptionPct": "VWh0dG_subscriptionPct",
132
- "shareSegOff": "VWh0dG_shareSegOff",
133
- "deltaUp": "VWh0dG_deltaUp",
134
- "estimatedTag": "VWh0dG_estimatedTag",
135
- "siteRowTitle": "VWh0dG_siteRowTitle",
95
+ "roundsAxis": "VWh0dG_roundsAxis",
96
+ "subscriptionWindow": "VWh0dG_subscriptionWindow",
97
+ "pricingChevronOpen": "VWh0dG_pricingChevronOpen",
136
98
  "balanceDaysBadgeLow": "VWh0dG_balanceDaysBadgeLow",
99
+ "triggerPopMetricValue": "VWh0dG_triggerPopMetricValue",
100
+ "triggerPopBadgeDirect": "VWh0dG_triggerPopBadgeDirect",
101
+ "roundsBarColPeak": "VWh0dG_roundsBarColPeak",
102
+ "roundsBarColOff": "VWh0dG_roundsBarColOff",
103
+ "peakAlertCenter": "VWh0dG_peakAlertCenter",
137
104
  "triggerPopMetricHighlight": "VWh0dG_triggerPopMetricHighlight",
138
- "chartTooltip": "VWh0dG_chartTooltip",
139
- "healthIdle": "VWh0dG_healthIdle",
140
- "subscriptionFill": "VWh0dG_subscriptionFill",
141
- "heatmapCell": "VWh0dG_heatmapCell",
142
- "peakAlertCheck": "VWh0dG_peakAlertCheck",
143
- "floatSub": "VWh0dG_floatSub",
144
- "shareLegend": "VWh0dG_shareLegend",
145
- "peakAlert": "VWh0dG_peakAlert",
146
- "triggerSparkHot": "VWh0dG_triggerSparkHot",
147
- "triggerPopTitle": "VWh0dG_triggerPopTitle",
148
- "heroGaugePct": "VWh0dG_heroGaugePct",
149
- "modelCell": "VWh0dG_modelCell",
150
- "floatModeRow": "VWh0dG_floatModeRow",
151
- "triggerPopName": "VWh0dG_triggerPopName",
152
- "siteKindDirect": "VWh0dG_siteKindDirect",
153
- "shareSegUser": "VWh0dG_shareSegUser",
154
- "heatmapFooter": "VWh0dG_heatmapFooter",
155
- "roundsBar": "VWh0dG_roundsBar",
156
- "heatmapLegend": "VWh0dG_heatmapLegend",
157
- "triggerPopFootNotes": "VWh0dG_triggerPopFootNotes",
158
- "panelHint": "VWh0dG_panelHint",
159
- "rateBadgeLive": "VWh0dG_rateBadgeLive",
160
- "chartLegendLine": "VWh0dG_chartLegendLine",
161
- "pricingChevron": "VWh0dG_pricingChevron",
162
- "closeButton": "VWh0dG_closeButton",
163
- "exportLabel": "VWh0dG_exportLabel",
164
- "liveQuotaCrit": "VWh0dG_liveQuotaCrit",
165
- "heatmapYearGrid": "VWh0dG_heatmapYearGrid",
166
- "budgetFillOver": "VWh0dG_budgetFillOver",
105
+ "modelTable": "VWh0dG_modelTable",
106
+ "pluginInfoLabel": "VWh0dG_pluginInfoLabel",
107
+ "heroGauge": "VWh0dG_heroGauge",
108
+ "triggerPopValueStack": "VWh0dG_triggerPopValueStack",
109
+ "triggerPopSwitchBtn": "VWh0dG_triggerPopSwitchBtn",
110
+ "shareSeg": "VWh0dG_shareSeg",
111
+ "billing-trigger": "VWh0dG_billing-trigger",
112
+ "deltaUp": "VWh0dG_deltaUp",
113
+ "heroTop": "VWh0dG_heroTop",
114
+ "budgetInputWrap": "VWh0dG_budgetInputWrap",
115
+ "balanceDetailGrid": "VWh0dG_balanceDetailGrid",
116
+ "peakAlertPanelLabel": "VWh0dG_peakAlertPanelLabel",
117
+ "budgetValue": "VWh0dG_budgetValue",
167
118
  "healthBadgeOk": "VWh0dG_healthBadgeOk",
168
- "triggerPopFootStatus": "VWh0dG_triggerPopFootStatus",
169
- "shareItem": "VWh0dG_shareItem",
170
- "kpiDetail": "VWh0dG_kpiDetail",
171
- "triggerPopMetric": "VWh0dG_triggerPopMetric",
172
- "peakAlertClose": "VWh0dG_peakAlertClose",
173
- "triggerRow": "VWh0dG_triggerRow",
174
- "bucketThird": "VWh0dG_bucketThird",
175
- "balanceDetailPop": "VWh0dG_balanceDetailPop",
176
- "panelTitle": "VWh0dG_panelTitle",
177
- "heatmapYearMonth": "VWh0dG_heatmapYearMonth",
178
- "tokenModelParts": "VWh0dG_tokenModelParts",
179
- "exportButton": "VWh0dG_exportButton",
180
- "peakAlertSelect": "VWh0dG_peakAlertSelect",
181
- "reconcileNotice": "VWh0dG_reconcileNotice",
182
- "exportBar": "VWh0dG_exportBar",
183
- "triggerPopFootStrong": "VWh0dG_triggerPopFootStrong",
184
- "heatmapRangeSwitch": "VWh0dG_heatmapRangeSwitch",
185
- "triggerAmount": "VWh0dG_triggerAmount",
119
+ "triggerPopBadge": "VWh0dG_triggerPopBadge",
120
+ "liveCostItem": "VWh0dG_liveCostItem",
186
121
  "kpiLabel": "VWh0dG_kpiLabel",
187
- "triggerSparkBar": "VWh0dG_triggerSparkBar",
188
- "triggerPopStrong": "VWh0dG_triggerPopStrong",
122
+ "siteRowCost": "VWh0dG_siteRowCost",
123
+ "roundsEmpty": "VWh0dG_roundsEmpty",
124
+ "peakAlertOff": "VWh0dG_peakAlertOff",
125
+ "subscriptionFillOver": "VWh0dG_subscriptionFillOver",
126
+ "panel": "VWh0dG_panel",
127
+ "heroGaugeCenter": "VWh0dG_heroGaugeCenter",
128
+ "chartBarPlaceholder": "VWh0dG_chartBarPlaceholder",
129
+ "heroReadout": "VWh0dG_heroReadout",
130
+ "modelProvider": "VWh0dG_modelProvider",
131
+ "subscriptionGrid": "VWh0dG_subscriptionGrid",
132
+ "roundsBarLabel": "VWh0dG_roundsBarLabel",
189
133
  "heatmapYear": "VWh0dG_heatmapYear",
190
- "heroCurrency": "VWh0dG_heroCurrency",
134
+ "triggerPopFootNote": "VWh0dG_triggerPopFootNote",
135
+ "triggerPopFoot": "VWh0dG_triggerPopFoot",
136
+ "heatmap": "VWh0dG_heatmap",
137
+ "roundsFlagBadge": "VWh0dG_roundsFlagBadge",
138
+ "tokenModelPartIn": "VWh0dG_tokenModelPartIn",
139
+ "heroSideSpacer": "VWh0dG_heroSideSpacer",
140
+ "triggerWrap": "VWh0dG_triggerWrap",
141
+ "shareSegPeak": "VWh0dG_shareSegPeak",
142
+ "tabPanel": "VWh0dG_tabPanel",
143
+ "tabButton": "VWh0dG_tabButton",
144
+ "triggerPopMetrics": "VWh0dG_triggerPopMetrics",
145
+ "triggerPopHead": "VWh0dG_triggerPopHead",
146
+ "currencyToggle": "VWh0dG_currencyToggle",
147
+ "bucketOfficial": "VWh0dG_bucketOfficial",
191
148
  "settingsTitle": "VWh0dG_settingsTitle",
192
- "subscriptionTier": "VWh0dG_subscriptionTier",
149
+ "railButton": "VWh0dG_railButton",
150
+ "providerGroupTitle": "VWh0dG_providerGroupTitle",
151
+ "kpiGrid": "VWh0dG_kpiGrid",
152
+ "reconcileDismiss": "VWh0dG_reconcileDismiss",
153
+ "healthBad": "VWh0dG_healthBad",
154
+ "budgetOverPulse": "VWh0dG_budgetOverPulse",
155
+ "triggerPopFootTitle": "VWh0dG_triggerPopFootTitle",
156
+ "siteKindTag": "VWh0dG_siteKindTag",
193
157
  "triggerPopSwitcher": "VWh0dG_triggerPopSwitcher",
194
- "panelHead": "VWh0dG_panelHead",
158
+ "triggerAmount": "VWh0dG_triggerAmount",
159
+ "currencyButtonActive": "VWh0dG_currencyButtonActive",
160
+ "providerGroupBalanceLabel": "VWh0dG_providerGroupBalanceLabel",
161
+ "budgetLabel": "VWh0dG_budgetLabel",
162
+ "heatmapRangeButton": "VWh0dG_heatmapRangeButton",
163
+ "bucketStat": "VWh0dG_bucketStat",
195
164
  "tabButtonActive": "VWh0dG_tabButtonActive",
196
- "liveTierPeak": "VWh0dG_liveTierPeak",
197
- "heatmapYearScroll": "VWh0dG_heatmapYearScroll",
198
- "chartTooltipRow": "VWh0dG_chartTooltipRow",
199
- "pricingToggle": "VWh0dG_pricingToggle",
165
+ "peakAlertSelect": "VWh0dG_peakAlertSelect",
166
+ "triggerPopStrong": "VWh0dG_triggerPopStrong",
200
167
  "emptyRow": "VWh0dG_emptyRow",
201
- "triggerPopSwitchCount": "VWh0dG_triggerPopSwitchCount",
202
- "reconcileDismiss": "VWh0dG_reconcileDismiss",
203
- "triggerPopFootTitle": "VWh0dG_triggerPopFootTitle",
204
- "heroSideSpacer": "VWh0dG_heroSideSpacer",
205
- "uncataloguedTag": "VWh0dG_uncataloguedTag",
206
- "rateBadge": "VWh0dG_rateBadge",
207
- "subscriptionName": "VWh0dG_subscriptionName",
208
- "tabNav": "VWh0dG_tabNav",
209
- "rangeButton": "VWh0dG_rangeButton",
210
- "heroMeta": "VWh0dG_heroMeta",
211
- "switchKnob": "VWh0dG_switchKnob",
212
- "heatmapYearWeekdays": "VWh0dG_heatmapYearWeekdays",
168
+ "liveCostBar": "VWh0dG_liveCostBar",
169
+ "reconcileIcon": "VWh0dG_reconcileIcon",
213
170
  "planTag": "VWh0dG_planTag",
171
+ "liveTierPeak": "VWh0dG_liveTierPeak",
172
+ "subscriptionTier": "VWh0dG_subscriptionTier",
173
+ "deltaDown": "VWh0dG_deltaDown",
174
+ "chartLine": "VWh0dG_chartLine",
175
+ "subscriptionGoldFlow": "VWh0dG_subscriptionGoldFlow",
176
+ "na": "VWh0dG_na",
177
+ "modelDot": "VWh0dG_modelDot",
178
+ "triggerPopFootNotes": "VWh0dG_triggerPopFootNotes",
214
179
  "heroGaugeSvg": "VWh0dG_heroGaugeSvg",
215
- "shareTrack": "VWh0dG_shareTrack",
216
- "heatmapGrid": "VWh0dG_heatmapGrid",
217
- "floatSubPlan": "VWh0dG_floatSubPlan",
218
- "triggerPop": "VWh0dG_triggerPop",
219
- "roundsAxis": "VWh0dG_roundsAxis",
220
- "pluginInfoRow": "VWh0dG_pluginInfoRow",
221
- "triggerSub": "VWh0dG_triggerSub",
180
+ "bucketThird": "VWh0dG_bucketThird",
181
+ "heatmapYearWeekdays": "VWh0dG_heatmapYearWeekdays",
182
+ "heroSideValue": "VWh0dG_heroSideValue",
183
+ "triggerPopAlert": "VWh0dG_triggerPopAlert",
222
184
  "heroLabel": "VWh0dG_heroLabel",
223
- "peakAlertText": "VWh0dG_peakAlertText",
224
- "bucketStatValue": "VWh0dG_bucketStatValue",
225
- "costCol": "VWh0dG_costCol",
226
- "delta": "VWh0dG_delta",
227
- "modelTableScroll": "VWh0dG_modelTableScroll",
228
- "settingsHint": "VWh0dG_settingsHint",
229
- "bucketSep": "VWh0dG_bucketSep",
230
- "chartLegendBar": "VWh0dG_chartLegendBar",
231
- "peakAlertPanel": "VWh0dG_peakAlertPanel",
232
- "heatmapCellEmpty": "VWh0dG_heatmapCellEmpty",
185
+ "triggerPopMuted": "VWh0dG_triggerPopMuted",
186
+ "switch": "VWh0dG_switch",
187
+ "chartLegendLine": "VWh0dG_chartLegendLine",
188
+ "balanceDaysLow": "VWh0dG_balanceDaysLow",
189
+ "floatModeRow": "VWh0dG_floatModeRow",
190
+ "floatModeBtnOn": "VWh0dG_floatModeBtnOn",
191
+ "heatmapGrid": "VWh0dG_heatmapGrid",
192
+ "providerGroupList": "VWh0dG_providerGroupList",
193
+ "heroGaugeTrack": "VWh0dG_heroGaugeTrack",
194
+ "heroGaugePctOver": "VWh0dG_heroGaugePctOver",
233
195
  "chartBar": "VWh0dG_chartBar",
234
- "triggerPopValueStack": "VWh0dG_triggerPopValueStack",
235
- "dashboardRight": "VWh0dG_dashboardRight",
236
- "healthBadgeBad": "VWh0dG_healthBadgeBad",
237
- "liveCostBar": "VWh0dG_liveCostBar",
238
- "liveCostItem": "VWh0dG_liveCostItem",
239
- "providerGroupBalance": "VWh0dG_providerGroupBalance",
240
- "peakAlertPreview": "VWh0dG_peakAlertPreview",
241
- "siteRow": "VWh0dG_siteRow",
242
- "pricingToggleText": "VWh0dG_pricingToggleText",
243
- "chartTooltipSwatch": "VWh0dG_chartTooltipSwatch",
196
+ "pricingTip": "VWh0dG_pricingTip",
197
+ "siteRowName": "VWh0dG_siteRowName",
198
+ "bandTagOff": "VWh0dG_bandTagOff",
199
+ "balanceDetailRow": "VWh0dG_balanceDetailRow",
244
200
  "subscriptionExhausted": "VWh0dG_subscriptionExhausted",
201
+ "bandPriceOff": "VWh0dG_bandPriceOff",
202
+ "triggerPopFootStatusLow": "VWh0dG_triggerPopFootStatusLow",
203
+ "exportLabel": "VWh0dG_exportLabel",
204
+ "currencyButton": "VWh0dG_currencyButton",
205
+ "heatmapRangeButtonActive": "VWh0dG_heatmapRangeButtonActive",
206
+ "peakAlertHint": "VWh0dG_peakAlertHint",
207
+ "triggerSparkBar": "VWh0dG_triggerSparkBar",
208
+ "tokenPanel": "VWh0dG_tokenPanel",
209
+ "providerGroupBadge": "VWh0dG_providerGroupBadge",
210
+ "chartDot": "VWh0dG_chartDot",
211
+ "exportBar": "VWh0dG_exportBar",
212
+ "chartLegendBar": "VWh0dG_chartLegendBar",
213
+ "siteKindDirect": "VWh0dG_siteKindDirect",
214
+ "budget": "VWh0dG_budget",
215
+ "estimatedTag": "VWh0dG_estimatedTag",
216
+ "kpiGreen": "VWh0dG_kpiGreen",
217
+ "heatmapYearMonth": "VWh0dG_heatmapYearMonth",
218
+ "heroGaugePct": "VWh0dG_heroGaugePct",
219
+ "triggerRow": "VWh0dG_triggerRow",
220
+ "peakAlertPanelBody": "VWh0dG_peakAlertPanelBody",
221
+ "roundsBars": "VWh0dG_roundsBars",
222
+ "balanceDetailLabel": "VWh0dG_balanceDetailLabel",
223
+ "shareDot": "VWh0dG_shareDot",
224
+ "chartTooltipSwatch": "VWh0dG_chartTooltipSwatch",
225
+ "heatmapYearMonths": "VWh0dG_heatmapYearMonths",
226
+ "heroGaugeArcOver": "VWh0dG_heroGaugeArcOver",
227
+ "healthBadge": "VWh0dG_healthBadge",
228
+ "budgetHint": "VWh0dG_budgetHint",
229
+ "dashboardBody": "VWh0dG_dashboardBody",
230
+ "rangeButtonActive": "VWh0dG_rangeButtonActive",
231
+ "reconcileNotice": "VWh0dG_reconcileNotice",
245
232
  "budgetTrack": "VWh0dG_budgetTrack",
246
- "reconcileText": "VWh0dG_reconcileText",
247
- "triggerPopLabel": "VWh0dG_triggerPopLabel",
248
- "subscriptionAuto": "VWh0dG_subscriptionAuto",
233
+ "chartCrosshair": "VWh0dG_chartCrosshair",
234
+ "heroGaugeLabel": "VWh0dG_heroGaugeLabel",
235
+ "chartAxisLabel": "VWh0dG_chartAxisLabel",
236
+ "shareSegOff": "VWh0dG_shareSegOff",
237
+ "chartTooltip": "VWh0dG_chartTooltip",
238
+ "chartGrid": "VWh0dG_chartGrid",
239
+ "heatmapCellEmpty": "VWh0dG_heatmapCellEmpty",
240
+ "healthBadgeBad": "VWh0dG_healthBadgeBad",
241
+ "triggerIcon": "VWh0dG_triggerIcon",
242
+ "kpiTile": "VWh0dG_kpiTile",
243
+ "heatmapFooter": "VWh0dG_heatmapFooter",
244
+ "heatmapYearScroll": "VWh0dG_heatmapYearScroll",
245
+ "floatTargetLabel": "VWh0dG_floatTargetLabel",
249
246
  "peakAlertIn": "VWh0dG_peakAlertIn",
250
- "kpiGrid": "VWh0dG_kpiGrid",
251
- "peakAlertCountdown": "VWh0dG_peakAlertCountdown",
252
- "settingsHead": "VWh0dG_settingsHead",
253
- "roundsBarColOff": "VWh0dG_roundsBarColOff",
247
+ "costCol": "VWh0dG_costCol",
248
+ "headTitleRow": "VWh0dG_headTitleRow",
249
+ "switchKnob": "VWh0dG_switchKnob",
250
+ "triggerPopTitle": "VWh0dG_triggerPopTitle",
251
+ "bucketCost": "VWh0dG_bucketCost",
252
+ "providerGroupBalance": "VWh0dG_providerGroupBalance",
253
+ "shareItem": "VWh0dG_shareItem",
254
+ "siteRowCallsLow": "VWh0dG_siteRowCallsLow",
255
+ "heatmapHover": "VWh0dG_heatmapHover",
256
+ "subscriptionPct": "VWh0dG_subscriptionPct",
257
+ "peakAlertPeak": "VWh0dG_peakAlertPeak",
258
+ "hero": "VWh0dG_hero",
259
+ "closeButton": "VWh0dG_closeButton",
260
+ "bucketSep": "VWh0dG_bucketSep",
261
+ "roundsBar": "VWh0dG_roundsBar",
262
+ "heroCurrency": "VWh0dG_heroCurrency",
263
+ "chartWrap": "VWh0dG_chartWrap",
264
+ "delta": "VWh0dG_delta",
265
+ "pricingToggle": "VWh0dG_pricingToggle",
266
+ "subscriptionHead": "VWh0dG_subscriptionHead",
267
+ "roundsBarCol": "VWh0dG_roundsBarCol",
254
268
  "heroValue": "VWh0dG_heroValue",
255
- "bucketStat": "VWh0dG_bucketStat",
269
+ "siteRowTitle": "VWh0dG_siteRowTitle",
270
+ "healthOk": "VWh0dG_healthOk",
271
+ "dashboardHead": "VWh0dG_dashboardHead",
272
+ "heroMeta": "VWh0dG_heroMeta",
273
+ "liveCostSep": "VWh0dG_liveCostSep",
274
+ "pluginInfoLink": "VWh0dG_pluginInfoLink",
275
+ "tokenModelParts": "VWh0dG_tokenModelParts",
276
+ "chartSvg": "VWh0dG_chartSvg",
277
+ "liveQuotaCrit": "VWh0dG_liveQuotaCrit",
278
+ "balanceDetailValue": "VWh0dG_balanceDetailValue",
279
+ "rateBadgeBuiltin": "VWh0dG_rateBadgeBuiltin",
280
+ "balanceDetailTitle": "VWh0dG_balanceDetailTitle",
281
+ "heroSideItem": "VWh0dG_heroSideItem",
282
+ "exportButton": "VWh0dG_exportButton",
283
+ "shareSegAssistant": "VWh0dG_shareSegAssistant",
284
+ "chartLegend": "VWh0dG_chartLegend",
285
+ "subscriptionWindowLabel": "VWh0dG_subscriptionWindowLabel",
286
+ "tabNav": "VWh0dG_tabNav",
287
+ "peakAlertCorner": "VWh0dG_peakAlertCorner",
288
+ "heroSideLabel": "VWh0dG_heroSideLabel",
289
+ "pluginInfo": "VWh0dG_pluginInfo",
290
+ "dashboard": "VWh0dG_dashboard",
291
+ "heatmapYearBody": "VWh0dG_heatmapYearBody",
292
+ "flatTag": "VWh0dG_flatTag",
293
+ "modelName": "VWh0dG_modelName",
294
+ "dashboardModal": "VWh0dG_dashboardModal",
295
+ "providerGroupMeta": "VWh0dG_providerGroupMeta",
296
+ "triggerPopLabel": "VWh0dG_triggerPopLabel",
297
+ "triggerPopValue": "VWh0dG_triggerPopValue",
298
+ "kpiDetail": "VWh0dG_kpiDetail",
299
+ "balanceDays": "VWh0dG_balanceDays",
300
+ "subscriptionPlan": "VWh0dG_subscriptionPlan",
301
+ "bucketStatValue": "VWh0dG_bucketStatValue",
302
+ "tabPanelIn": "VWh0dG_tabPanelIn",
303
+ "chartEmpty": "VWh0dG_chartEmpty",
304
+ "triggerPopBars": "VWh0dG_triggerPopBars",
305
+ "switchOn": "VWh0dG_switchOn",
306
+ "shareLegend": "VWh0dG_shareLegend",
307
+ "shareSegTool": "VWh0dG_shareSegTool",
308
+ "chartTooltipDate": "VWh0dG_chartTooltipDate",
309
+ "triggerPopMetric": "VWh0dG_triggerPopMetric",
310
+ "triggerPopEmpty": "VWh0dG_triggerPopEmpty",
311
+ "triggerSpark": "VWh0dG_triggerSpark",
312
+ "shareTrack": "VWh0dG_shareTrack",
313
+ "trendPanel": "VWh0dG_trendPanel",
314
+ "heatmapCell": "VWh0dG_heatmapCell",
315
+ "siteKindSite": "VWh0dG_siteKindSite",
316
+ "rounds": "VWh0dG_rounds",
317
+ "floatSubName": "VWh0dG_floatSubName",
318
+ "uncataloguedTag": "VWh0dG_uncataloguedTag",
319
+ "budgetUnit": "VWh0dG_budgetUnit",
320
+ "tokenModelShareRow": "VWh0dG_tokenModelShareRow",
321
+ "peakAlertPanelHead": "VWh0dG_peakAlertPanelHead",
322
+ "panelHead": "VWh0dG_panelHead",
323
+ "triggerPopTitleMonth": "VWh0dG_triggerPopTitleMonth",
324
+ "budgetControls": "VWh0dG_budgetControls",
256
325
  "balanceCell": "VWh0dG_balanceCell",
257
- "siteKindTag": "VWh0dG_siteKindTag",
258
- "triggerPopFootStatusLow": "VWh0dG_triggerPopFootStatusLow",
259
- "modelTable": "VWh0dG_modelTable",
260
- "roundsBarWrap": "VWh0dG_roundsBarWrap",
261
- "heatmapYearCell": "VWh0dG_heatmapYearCell",
262
- "heatmapRangeButtonActive": "VWh0dG_heatmapRangeButtonActive",
263
- "siteRowCallsLow": "VWh0dG_siteRowCallsLow",
264
- "providerGroupBadge": "VWh0dG_providerGroupBadge",
265
- "kpiValue": "VWh0dG_kpiValue",
266
- "triggerBody": "VWh0dG_triggerBody",
267
- "bucketSummary": "VWh0dG_bucketSummary",
268
- "dashboardSubtitle": "VWh0dG_dashboardSubtitle",
326
+ "unpricedHint": "VWh0dG_unpricedHint",
327
+ "healthIdle": "VWh0dG_healthIdle",
328
+ "settingsHead": "VWh0dG_settingsHead",
329
+ "balanceDaysBadge": "VWh0dG_balanceDaysBadge",
330
+ "siteRowCalls": "VWh0dG_siteRowCalls",
331
+ "triggerPopBadgeSub": "VWh0dG_triggerPopBadgeSub",
332
+ "triggerPopSwitchCount": "VWh0dG_triggerPopSwitchCount",
333
+ "dashboardRight": "VWh0dG_dashboardRight",
334
+ "heatmapRangeSwitch": "VWh0dG_heatmapRangeSwitch",
335
+ "triggerPopFootStatus": "VWh0dG_triggerPopFootStatus",
336
+ "budgetHead": "VWh0dG_budgetHead",
269
337
  "peakAlertNum": "VWh0dG_peakAlertNum",
270
- "modelProvider": "VWh0dG_modelProvider",
271
- "peakAlertPanelHead": "VWh0dG_peakAlertPanelHead",
272
- "chartGrid": "VWh0dG_chartGrid",
273
- "rangeToggle": "VWh0dG_rangeToggle",
274
- "chartCrosshair": "VWh0dG_chartCrosshair",
275
338
  "peakAlertField": "VWh0dG_peakAlertField",
276
- "roundsFlagMark": "VWh0dG_roundsFlagMark",
277
- "triggerPopAlert": "VWh0dG_triggerPopAlert",
278
- "dashboardBody": "VWh0dG_dashboardBody",
279
- "dashboard": "VWh0dG_dashboard",
280
- "rounds": "VWh0dG_rounds",
281
- "triggerPopHead": "VWh0dG_triggerPopHead",
282
- "panel": "VWh0dG_panel",
283
- "balanceDetailGrid": "VWh0dG_balanceDetailGrid",
284
- "providerGroupHead": "VWh0dG_providerGroupHead",
285
- "peakAlertOff": "VWh0dG_peakAlertOff",
286
- "peakAlertTag": "VWh0dG_peakAlertTag",
339
+ "triggerPopName": "VWh0dG_triggerPopName",
287
340
  "subscriptionReset": "VWh0dG_subscriptionReset",
288
- "heroTop": "VWh0dG_heroTop",
289
- "tokenModelShareRow": "VWh0dG_tokenModelShareRow",
290
- "heroGaugeTrack": "VWh0dG_heroGaugeTrack",
291
- "pricingTip": "VWh0dG_pricingTip",
292
- "switch": "VWh0dG_switch",
293
- "hero": "VWh0dG_hero",
294
- "na": "VWh0dG_na",
295
- "balanceDetailValue": "VWh0dG_balanceDetailValue",
296
- "triggerPopSubscription": "VWh0dG_triggerPopSubscription",
297
- "subscriptionHead": "VWh0dG_subscriptionHead",
298
- "triggerPopBadgeSub": "VWh0dG_triggerPopBadgeSub",
299
- "providerGroup": "VWh0dG_providerGroup",
300
- "budgetFill": "VWh0dG_budgetFill",
301
- "chartWrap": "VWh0dG_chartWrap",
302
- "floatModeBtnOn": "VWh0dG_floatModeBtnOn",
303
- "heroGaugeCenter": "VWh0dG_heroGaugeCenter",
304
- "dashboardModal": "VWh0dG_dashboardModal",
305
- "healthDot": "VWh0dG_healthDot",
306
- "healthBadge": "VWh0dG_healthBadge",
307
- "liveCostSep": "VWh0dG_liveCostSep",
308
- "heroGaugeArc": "VWh0dG_heroGaugeArc",
309
- "triggerPopUpdated": "VWh0dG_triggerPopUpdated",
310
- "bandPriceOff": "VWh0dG_bandPriceOff",
311
- "heatmapYearBody": "VWh0dG_heatmapYearBody",
312
- "deltaDown": "VWh0dG_deltaDown",
313
- "heroGaugeArcOver": "VWh0dG_heroGaugeArcOver",
314
- "balanceDaysLow": "VWh0dG_balanceDaysLow",
315
- "kpiTile": "VWh0dG_kpiTile",
316
- "providerGroupName": "VWh0dG_providerGroupName",
317
- "floatTarget": "VWh0dG_floatTarget",
318
- "pricingChevronOpen": "VWh0dG_pricingChevronOpen",
319
- "triggerPopFootNote": "VWh0dG_triggerPopFootNote",
320
- "siteRowCalls": "VWh0dG_siteRowCalls",
321
- "balanceDaysBadge": "VWh0dG_balanceDaysBadge",
341
+ "pricingTable": "VWh0dG_pricingTable",
342
+ "heroSide": "VWh0dG_heroSide",
343
+ "bandPrice": "VWh0dG_bandPrice",
344
+ "peakAlert": "VWh0dG_peakAlert",
345
+ "balanceDetailClose": "VWh0dG_balanceDetailClose",
346
+ "settingsHint": "VWh0dG_settingsHint",
347
+ "pluginInfoRow": "VWh0dG_pluginInfoRow",
348
+ "subscriptionCard": "VWh0dG_subscriptionCard",
349
+ "balanceDetailHead": "VWh0dG_balanceDetailHead",
350
+ "reconcileText": "VWh0dG_reconcileText",
351
+ "dashboardSubtitle": "VWh0dG_dashboardSubtitle",
352
+ "triggerPopRow": "VWh0dG_triggerPopRow",
353
+ "budgetInput": "VWh0dG_budgetInput",
354
+ "siteRowMeta": "VWh0dG_siteRowMeta",
355
+ "pricingToggleText": "VWh0dG_pricingToggleText",
356
+ "subscriptionAuto": "VWh0dG_subscriptionAuto",
357
+ "providerGroupHead": "VWh0dG_providerGroupHead",
322
358
  "roundsBarFlagged": "VWh0dG_roundsBarFlagged",
323
- "tokenModelPartIn": "VWh0dG_tokenModelPartIn",
324
- "trendPanel": "VWh0dG_trendPanel",
325
- "currencyButton": "VWh0dG_currencyButton",
359
+ "floatTarget": "VWh0dG_floatTarget",
360
+ "liveQuotaWarn": "VWh0dG_liveQuotaWarn",
361
+ "triggerPop": "VWh0dG_triggerPop",
362
+ "triggerPopUpdated": "VWh0dG_triggerPopUpdated",
363
+ "triggerPopOpenBtn": "VWh0dG_triggerPopOpenBtn",
364
+ "panelHint": "VWh0dG_panelHint",
365
+ "triggerPopFootStrong": "VWh0dG_triggerPopFootStrong",
366
+ "kpiValue": "VWh0dG_kpiValue",
367
+ "subscriptionName": "VWh0dG_subscriptionName",
368
+ "peakAlertPanel": "VWh0dG_peakAlertPanel",
369
+ "modelTableScroll": "VWh0dG_modelTableScroll",
326
370
  "bandTag": "VWh0dG_bandTag",
327
- "heroReadout": "VWh0dG_heroReadout",
371
+ "providerGroup": "VWh0dG_providerGroup",
372
+ "pluginInfoValue": "VWh0dG_pluginInfoValue",
373
+ "subscriptionFill": "VWh0dG_subscriptionFill",
374
+ "heatmapYearCell": "VWh0dG_heatmapYearCell",
375
+ "peakAlertCheck": "VWh0dG_peakAlertCheck",
376
+ "staleNotice": "VWh0dG_staleNotice",
328
377
  "floatSubHead": "VWh0dG_floatSubHead",
329
- "peakAlertHint": "VWh0dG_peakAlertHint",
330
- "floatTargetLabel": "VWh0dG_floatTargetLabel",
331
- "subscriptionWindow": "VWh0dG_subscriptionWindow",
378
+ "peakAlertCountdown": "VWh0dG_peakAlertCountdown",
379
+ "subscriptionStatus": "VWh0dG_subscriptionStatus",
380
+ "heatmapLegend": "VWh0dG_heatmapLegend",
381
+ "heatmapYearWeekday": "VWh0dG_heatmapYearWeekday",
382
+ "peakAlertClose": "VWh0dG_peakAlertClose",
383
+ "triggerPopSubscription": "VWh0dG_triggerPopSubscription",
384
+ "dashboardIn": "VWh0dG_dashboardIn",
385
+ "pricingChevron": "VWh0dG_pricingChevron",
386
+ "trigger": "VWh0dG_trigger",
387
+ "triggerPopBar": "VWh0dG_triggerPopBar",
388
+ "panelTitle": "VWh0dG_panelTitle",
389
+ "siteRow": "VWh0dG_siteRow",
390
+ "dashboardTitle": "VWh0dG_dashboardTitle",
332
391
  "heroMain": "VWh0dG_heroMain",
333
- "budgetLabel": "VWh0dG_budgetLabel",
334
- "triggerPopMetrics": "VWh0dG_triggerPopMetrics",
335
- "triggerPopOpenBtn": "VWh0dG_triggerPopOpenBtn",
336
- "budgetHead": "VWh0dG_budgetHead",
337
- "roundsEmpty": "VWh0dG_roundsEmpty",
338
- "tabPanel": "VWh0dG_tabPanel",
339
- "reconcileIcon": "VWh0dG_reconcileIcon",
340
- "billing-trigger": "VWh0dG_billing-trigger",
341
- "chartAxisLabel": "VWh0dG_chartAxisLabel",
342
- "triggerPopRow": "VWh0dG_triggerPopRow",
343
- "chartSvg": "VWh0dG_chartSvg",
344
- "providerGroupList": "VWh0dG_providerGroupList",
345
- "providerGroupTitle": "VWh0dG_providerGroupTitle",
346
- "triggerPopEmpty": "VWh0dG_triggerPopEmpty",
392
+ "rangeButton": "VWh0dG_rangeButton",
393
+ "healthDot": "VWh0dG_healthDot",
394
+ "bucketStatSub": "VWh0dG_bucketStatSub",
395
+ "shareValue": "VWh0dG_shareValue",
396
+ "subscriptionMeta": "VWh0dG_subscriptionMeta",
397
+ "roundsBarWrap": "VWh0dG_roundsBarWrap",
398
+ "heatmapYearGrid": "VWh0dG_heatmapYearGrid",
399
+ "floatSubPlan": "VWh0dG_floatSubPlan",
400
+ "triggerBody": "VWh0dG_triggerBody",
401
+ "tableScroll": "VWh0dG_tableScroll",
402
+ "triggerPopMetricLabel": "VWh0dG_triggerPopMetricLabel",
403
+ "peakAlertTag": "VWh0dG_peakAlertTag",
404
+ "modelCell": "VWh0dG_modelCell",
405
+ "tokenModelBar": "VWh0dG_tokenModelBar",
347
406
  "triggerMeta": "VWh0dG_triggerMeta",
348
- "triggerPopFoot": "VWh0dG_triggerPopFoot",
349
- "rangeButtonActive": "VWh0dG_rangeButtonActive",
350
- "heroSide": "VWh0dG_heroSide",
351
- "chartDot": "VWh0dG_chartDot",
352
- "subscriptionCard": "VWh0dG_subscriptionCard",
353
- "subscriptionStatus": "VWh0dG_subscriptionStatus",
354
- "budgetInputWrap": "VWh0dG_budgetInputWrap",
355
- "triggerWrap": "VWh0dG_triggerWrap",
356
- "triggerPopBars": "VWh0dG_triggerPopBars",
357
- "triggerPopValue": "VWh0dG_triggerPopValue",
358
- "balanceDetailHead": "VWh0dG_balanceDetailHead",
359
- "pluginInfoLink": "VWh0dG_pluginInfoLink",
360
- "pluginInfo": "VWh0dG_pluginInfo",
361
- "currencyToggle": "VWh0dG_currencyToggle",
362
- "peakAlertCorner": "VWh0dG_peakAlertCorner",
363
- "heatmapRangeButton": "VWh0dG_heatmapRangeButton",
364
- "shareDot": "VWh0dG_shareDot",
365
- "heroSideItem": "VWh0dG_heroSideItem",
366
- "bucketStatLabel": "VWh0dG_bucketStatLabel",
367
- "modelDot": "VWh0dG_modelDot",
368
- "subscriptionGoldFlow": "VWh0dG_subscriptionGoldFlow",
369
- "triggerPopMuted": "VWh0dG_triggerPopMuted",
370
- "siteKindSite": "VWh0dG_siteKindSite",
371
- "headTitleRow": "VWh0dG_headTitleRow",
372
- "pluginInfoLabel": "VWh0dG_pluginInfoLabel",
373
- "peakAlertCenter": "VWh0dG_peakAlertCenter",
374
- "liveQuotaWarn": "VWh0dG_liveQuotaWarn",
375
- "peakAlertPanelBody": "VWh0dG_peakAlertPanelBody",
376
- "budgetControls": "VWh0dG_budgetControls",
377
- "triggerPopTitleMonth": "VWh0dG_triggerPopTitleMonth",
378
- "modelName": "VWh0dG_modelName",
379
- "shareSeg": "VWh0dG_shareSeg",
380
- "budgetInput": "VWh0dG_budgetInput",
381
- "tabButton": "VWh0dG_tabButton",
382
- "balanceDetailTitle": "VWh0dG_balanceDetailTitle",
407
+ "rateBadge": "VWh0dG_rateBadge",
408
+ "balanceDetailPop": "VWh0dG_balanceDetailPop",
409
+ "peakAlertText": "VWh0dG_peakAlertText",
410
+ "heroGaugeArc": "VWh0dG_heroGaugeArc",
411
+ "subscriptionTrack": "VWh0dG_subscriptionTrack",
383
412
  "triggerPopFootName": "VWh0dG_triggerPopFootName",
384
- "siteRowName": "VWh0dG_siteRowName",
385
- "subscriptionFillWarn": "VWh0dG_subscriptionFillWarn",
386
- "heroGaugeLabel": "VWh0dG_heroGaugeLabel",
387
- "siteKindUnknown": "VWh0dG_siteKindUnknown",
388
- "budgetOverPulse": "VWh0dG_budgetOverPulse",
389
- "roundsBars": "VWh0dG_roundsBars",
390
- "bucketCost": "VWh0dG_bucketCost",
391
- "budgetUnit": "VWh0dG_budgetUnit",
392
- "chartBarPlaceholder": "VWh0dG_chartBarPlaceholder",
393
- "balanceDetailLabel": "VWh0dG_balanceDetailLabel",
394
- "triggerPopBar": "VWh0dG_triggerPopBar",
395
- "floatModeBtn": "VWh0dG_floatModeBtn",
396
- "rateBadgeBuiltin": "VWh0dG_rateBadgeBuiltin",
397
- "budgetFillWarn": "VWh0dG_budgetFillWarn",
398
- "heroGauge": "VWh0dG_heroGauge",
399
- "heroSideValue": "VWh0dG_heroSideValue",
400
- "triggerPopBadge": "VWh0dG_triggerPopBadge",
401
- "staleNotice": "VWh0dG_staleNotice",
402
- "chartTooltipDate": "VWh0dG_chartTooltipDate",
403
- "subscriptionPlan": "VWh0dG_subscriptionPlan",
404
- "roundsBarCol": "VWh0dG_roundsBarCol",
405
- "pluginInfoValue": "VWh0dG_pluginInfoValue",
406
- "chartEmpty": "VWh0dG_chartEmpty"
413
+ "bucketSummary": "VWh0dG_bucketSummary"
407
414
  };
408
415
  //#endregion
409
416
  //#region src/client/plan-knowledge.ts
@@ -452,6 +459,7 @@ window.__ModuleLoader__.load({
452
459
  "ark-token-plan": { type: "code" },
453
460
  "doubao-token-plan": { type: "code" },
454
461
  "minimax": { type: "code" },
462
+ "minimax-cn": { type: "code" },
455
463
  "minimax-token-plan": { type: "code" },
456
464
  "minimax-token-plan-cn": { type: "code" }
457
465
  };
@@ -548,16 +556,6 @@ window.__ModuleLoader__.load({
548
556
  output: 10
549
557
  }
550
558
  ];
551
- //#endregion
552
- //#region src/client/pricing.ts
553
- /**
554
- * USD → CNY rate for display. Source: China Foreign Exchange Trade System
555
- * mid-rate 6.7878 on 2026-08-14; rounded to 6.79. Only applies to overseas
556
- * USD-priced models — domestic models never pass through this rate.
557
- * The node half may refresh this at boot via `/api/billing/pricing`; until a
558
- * live rate arrives the built-in value stays in force.
559
- */
560
- const USD_TO_CNY = 6.79;
561
559
  /** 运行时实时覆盖:undefined = 用内置目录与内置汇率(默认值降级)。 */
562
560
  let liveRate;
563
561
  let livePrices;
@@ -569,7 +567,7 @@ window.__ModuleLoader__.load({
569
567
  * @param pricing - the `/api/billing/pricing` response.
570
568
  */
571
569
  function applyLivePricing(pricing) {
572
- liveRate = pricing.rate;
570
+ liveRate = typeof pricing.rate === "number" && Number.isFinite(pricing.rate) && pricing.rate > 0 ? pricing.rate : void 0;
573
571
  livePrices = pricing.prices;
574
572
  liveExtraModels = pricing.extraModels;
575
573
  }
@@ -1213,7 +1211,10 @@ window.__ModuleLoader__.load({
1213
1211
  "step-3.7-flash": "step",
1214
1212
  "seed-2.0-mini": "doubao-mini",
1215
1213
  "k3": "kimi-k3",
1216
- "kimi-k3": "kimi-k3"
1214
+ "kimi-k3": "kimi-k3",
1215
+ "minimax-m1": "minimax",
1216
+ "minimax-m2": "minimax",
1217
+ "minimax-m3": "minimax"
1217
1218
  };
1218
1219
  /**
1219
1220
  * 模型 id 归一化:小写、去括号附注(如 `gpt5.6 luna(go)` 只看主体)、再去所有
@@ -1326,11 +1327,9 @@ window.__ModuleLoader__.load({
1326
1327
  return MODEL_CATALOG.find((item) => item.key === aliasKey);
1327
1328
  })() !== void 0) continue;
1328
1329
  if (known.has(rawKey)) continue;
1329
- const extra = (liveExtraModels ?? []).find((item) => item.key === rawKey);
1330
- const fallbackLive = extra === void 0 ? livePriceOf(rawKey) : void 0;
1330
+ const fallbackLive = livePriceOf(rawKey);
1331
1331
  let entry;
1332
- if (extra !== void 0) entry = { ...extraEntryOf(extra) };
1333
- else if (fallbackLive !== void 0) entry = {
1332
+ if (fallbackLive !== void 0) entry = {
1334
1333
  key: rawKey,
1335
1334
  name: model.name ?? model.id,
1336
1335
  provider: model.provider,
@@ -1399,9 +1398,11 @@ window.__ModuleLoader__.load({
1399
1398
  const off = entry.price.offPeak === void 0 ? peak : priceBandCost(entry.price.offPeak, buckets, entry.price.currency);
1400
1399
  return peak * peakShare + off * (1 - peakShare);
1401
1400
  }
1402
- /** 人民币 → 美元(显示换算用):1 USD = {@link USD_TO_CNY} CNY。 */
1401
+ /** 人民币 → 美元(显示换算用):用当前生效汇率(实时优先,缺失回退内置),
1402
+ * 与计价链路的 `currentRate()` 同口径,避免实时汇率生效时 USD 显示与计价不一致。 */
1403
1403
  function cnyToUsd(cny) {
1404
- return cny / USD_TO_CNY;
1404
+ const rate = currentRate();
1405
+ return rate > 0 ? cny / rate : cny;
1405
1406
  }
1406
1407
  /**
1407
1408
  * Format an amount with adaptive precision and the given currency symbol.
@@ -2175,7 +2176,7 @@ window.__ModuleLoader__.load({
2175
2176
  * @param props.onTrendDays - 切换趋势窗口。
2176
2177
  */
2177
2178
  function TokenPanel(props) {
2178
- const { stats, currency: _currency, trendDays, onTrendDays, t } = props;
2179
+ const { stats, trendDays, onTrendDays, t } = props;
2179
2180
  const { byDay, byModel, total } = stats;
2180
2181
  const days = (0, react.useMemo)(() => {
2181
2182
  const out = [];
@@ -2276,7 +2277,7 @@ window.__ModuleLoader__.load({
2276
2277
  a.href = URL.createObjectURL(blob);
2277
2278
  a.download = `token-daily-${localStamp()}.csv`;
2278
2279
  a.click();
2279
- URL.revokeObjectURL(a.href);
2280
+ setTimeout(() => URL.revokeObjectURL(a.href), 0);
2280
2281
  };
2281
2282
  const exportTokenJson = () => {
2282
2283
  const blob = new Blob([JSON.stringify({
@@ -2288,7 +2289,7 @@ window.__ModuleLoader__.load({
2288
2289
  a.href = URL.createObjectURL(blob);
2289
2290
  a.download = `token-${localStamp()}.json`;
2290
2291
  a.click();
2291
- URL.revokeObjectURL(a.href);
2292
+ setTimeout(() => URL.revokeObjectURL(a.href), 0);
2292
2293
  };
2293
2294
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2294
2295
  className: UsageBilling_module_css_default.tokenPanel,
@@ -3046,12 +3047,12 @@ window.__ModuleLoader__.load({
3046
3047
  * @returns 异常标记数组(保持输入顺序)。
3047
3048
  */
3048
3049
  function flagAnomalies(rounds, options) {
3049
- const opts = {
3050
- ...DEFAULTS,
3051
- ...options
3052
- };
3050
+ const window = options?.window ?? DEFAULTS.window;
3051
+ const threshold = options?.threshold ?? DEFAULTS.threshold;
3052
+ const reasonFactor = options?.reasonFactor ?? DEFAULTS.reasonFactor;
3053
+ const reasonHitDropPp = options?.reasonHitDropPp ?? DEFAULTS.reasonHitDropPp;
3053
3054
  const flags = [];
3054
- if (opts.window <= 0 || opts.threshold <= 0) return flags;
3055
+ if (window <= 0 || threshold <= 0) return flags;
3055
3056
  const baselineCosts = [];
3056
3057
  const baselineOutputs = [];
3057
3058
  const baselineInputs = [];
@@ -3063,13 +3064,13 @@ window.__ModuleLoader__.load({
3063
3064
  const hit = cacheHitRate(round);
3064
3065
  const baselineCost = mean(baselineCosts);
3065
3066
  const reasons = [];
3066
- if (baselineCost !== null && baselineCost > 0 && round.cost > baselineCost * opts.threshold) {
3067
+ if (baselineCost !== null && baselineCost > 0 && round.cost > baselineCost * threshold) {
3067
3068
  const baselineOutput = mean(baselineOutputs);
3068
3069
  const baselineInput = mean(baselineInputs);
3069
3070
  const baselineHit = mean(baselineHits);
3070
- if (baselineOutput !== null && baselineOutput > 0 && output > baselineOutput * opts.reasonFactor) reasons.push("output-growth");
3071
- if (baselineInput !== null && baselineInput > 0 && input > baselineInput * opts.reasonFactor) reasons.push("context-bloat");
3072
- if (baselineHit !== null && hit !== null && hit < baselineHit - opts.reasonHitDropPp) reasons.push("cache-hit-drop");
3071
+ if (baselineOutput !== null && baselineOutput > 0 && output > baselineOutput * reasonFactor) reasons.push("output-growth");
3072
+ if (baselineInput !== null && baselineInput > 0 && input > baselineInput * reasonFactor) reasons.push("context-bloat");
3073
+ if (baselineHit !== null && hit !== null && hit < baselineHit - reasonHitDropPp) reasons.push("cache-hit-drop");
3073
3074
  flags.push({
3074
3075
  sessionId: round.sessionId,
3075
3076
  turn: round.turn,
@@ -3081,18 +3082,23 @@ window.__ModuleLoader__.load({
3081
3082
  baselineOutputs.push(output);
3082
3083
  baselineInputs.push(input);
3083
3084
  if (hit !== null) baselineHits.push(hit);
3084
- while (baselineCosts.length > opts.window) baselineCosts.shift();
3085
- while (baselineOutputs.length > opts.window) baselineOutputs.shift();
3086
- while (baselineInputs.length > opts.window) baselineInputs.shift();
3087
- while (baselineHits.length > opts.window) baselineHits.shift();
3085
+ while (baselineCosts.length > window) baselineCosts.shift();
3086
+ while (baselineOutputs.length > window) baselineOutputs.shift();
3087
+ while (baselineInputs.length > window) baselineInputs.shift();
3088
+ while (baselineHits.length > window) baselineHits.shift();
3088
3089
  }
3089
3090
  return flags;
3090
3091
  }
3091
3092
  //#endregion
3092
3093
  //#region src/client/export.ts
3093
- /** CSV 单元格转义:含逗号 / 引号 / 换行的值加双引号并内层引号双写。 */
3094
+ /** CSV 单元格转义:含逗号 / 引号 / 换行 / 回车的值加双引号并内层引号双写。 */
3094
3095
  function csvCell(value) {
3095
- return /[",\n]/.test(value) ? `"${value.replace(/"/g, "\"\"")}"` : value;
3096
+ return /[",\r\n]/.test(value) ? `"${value.replace(/"/g, "\"\"")}"` : value;
3097
+ }
3098
+ /** 防 CSV 公式注入:以 `=` / `+` / `-` / `@` / tab / 回车开头的值前置单引号,
3099
+ * 避免在 Excel/WPS 打开时被当作公式执行。用户/模型可控的会话标题会进 CSV。 */
3100
+ function csvSafe(value) {
3101
+ return /^[=+\-@\t\r]/.test(value) ? `'${value}` : value;
3096
3102
  }
3097
3103
  /** 金额保留两位小数字符串(导出对账用,不做千分位)。 */
3098
3104
  function money(value) {
@@ -3120,7 +3126,7 @@ window.__ModuleLoader__.load({
3120
3126
  const site = key.startsWith("site:") ? key.slice(5) : key.startsWith("direct:") ? key.slice(7) : "unknown";
3121
3127
  const kind = key.startsWith("site:") ? "site" : key.startsWith("direct:") ? "direct" : "unknown";
3122
3128
  return [
3123
- csvCell(site),
3129
+ csvCell(csvSafe(site)),
3124
3130
  kind,
3125
3131
  usage.calls,
3126
3132
  money(usage.cost)
@@ -3135,9 +3141,9 @@ window.__ModuleLoader__.load({
3135
3141
  /** 按会话 CSV:会话 id,标题,项目,调用,费用(元),最后活跃(ISO)。 */
3136
3142
  function sessionRowsCsv(rows) {
3137
3143
  return ["session_id,title,project,calls,cost_cny,last_active", ...rows.map((row) => [
3138
- csvCell(row.id),
3139
- csvCell(row.title ?? ""),
3140
- csvCell(projectOf(row.cwd)),
3144
+ csvCell(csvSafe(row.id)),
3145
+ csvCell(csvSafe(row.title ?? "")),
3146
+ csvCell(csvSafe(projectOf(row.cwd))),
3141
3147
  row.calls,
3142
3148
  money(row.cost),
3143
3149
  row.lastActive > 0 ? new Date(row.lastActive).toISOString() : ""
@@ -3157,7 +3163,7 @@ window.__ModuleLoader__.load({
3157
3163
  anchor.href = url;
3158
3164
  anchor.download = filename;
3159
3165
  anchor.click();
3160
- URL.revokeObjectURL(url);
3166
+ setTimeout(() => URL.revokeObjectURL(url), 0);
3161
3167
  }
3162
3168
  //#endregion
3163
3169
  //#region src/client/locales.ts
@@ -3731,6 +3737,13 @@ window.__ModuleLoader__.load({
3731
3737
  const timer = setInterval(() => setNowMs(Date.now()), 1e3);
3732
3738
  return () => clearInterval(timer);
3733
3739
  }, []);
3740
+ (0, react.useEffect)(() => {
3741
+ if (nowMs >= hit.atMs) onDismiss();
3742
+ }, [
3743
+ nowMs,
3744
+ hit.atMs,
3745
+ onDismiss
3746
+ ]);
3734
3747
  if (nowMs >= hit.atMs) return null;
3735
3748
  const minutes = Math.max(1, Math.round((hit.atMs - nowMs) / 6e4));
3736
3749
  const entering = hit.entering;
@@ -3954,6 +3967,7 @@ window.__ModuleLoader__.load({
3954
3967
  "baidu": "百度文心",
3955
3968
  "wenxin": "百度文心",
3956
3969
  "minimax": "MiniMax",
3970
+ "minimax-cn": "MiniMax",
3957
3971
  "minimax-token-plan": "MiniMax",
3958
3972
  "minimax-token-plan-cn": "MiniMax",
3959
3973
  "opencode": "OpenCode",
@@ -4208,54 +4222,60 @@ window.__ModuleLoader__.load({
4208
4222
  * fabricate.
4209
4223
  * @param attempt - current retry index (0-based).
4210
4224
  */
4225
+ /** 实时定价重试链是否已在进行:挂载/开弹窗/轮询多个调用点会并发触发 loadLivePricing,
4226
+ * 若都在 `builtin` 时各自起 setTimeout 重试链会叠加出多余请求,这里只保留一条。 */
4227
+ let livePricingRetryPending = false;
4211
4228
  async function loadLivePricing(attempt = 0) {
4212
4229
  const MAX_ATTEMPTS = 4;
4213
4230
  try {
4214
4231
  const response = await fetch(PRICING_PATH);
4215
- if (!response.ok) return;
4232
+ if (!response.ok) {
4233
+ livePricingRetryPending = false;
4234
+ return;
4235
+ }
4216
4236
  const text = await response.text();
4217
4237
  const parsed = JSON.parse(text);
4218
- if (parsed === null || typeof parsed !== "object" || !("source" in parsed)) return;
4238
+ if (parsed === null || typeof parsed !== "object" || !("source" in parsed)) {
4239
+ livePricingRetryPending = false;
4240
+ return;
4241
+ }
4219
4242
  const pricing = parsed;
4220
4243
  if (pricing.source === "builtin" && attempt < MAX_ATTEMPTS - 1) {
4244
+ if (attempt === 0) {
4245
+ if (livePricingRetryPending) return;
4246
+ livePricingRetryPending = true;
4247
+ }
4221
4248
  setTimeout(() => {
4222
4249
  loadLivePricing(attempt + 1);
4223
4250
  }, 2e3);
4224
4251
  return;
4225
4252
  }
4253
+ livePricingRetryPending = false;
4226
4254
  applyLivePricing(pricing);
4227
- } catch {}
4228
- }
4229
- /**
4230
- * 拉取各提供方账户余额(供模型计费明细表的余额列);失败返回空列表。
4231
- * @returns the balance rows, or an empty list on any failure.
4232
- */
4233
- async function fetchBalances() {
4234
- try {
4235
- const response = await fetch(BALANCE_PATH);
4236
- if (!response.ok) return [];
4237
- const text = await response.text();
4238
- const parsed = JSON.parse(text);
4239
- if (parsed !== null && typeof parsed === "object" && "balances" in parsed) return parsed.balances;
4240
- return [];
4241
4255
  } catch {
4242
- return [];
4256
+ livePricingRetryPending = false;
4243
4257
  }
4244
4258
  }
4245
4259
  /**
4246
- * 拉取官方余额差对账提示(drift 时非空),供余额面板展示;失败返回 undefined。
4247
- * @returns the reconcile notice, or undefined on any failure / no drift.
4260
+ * 一次拉取 `/api/billing/balance` 的完整响应(余额行 + 对账提示)。余额与对账
4261
+ * 提示来自同一响应体,拆成两个函数会导致每 30 秒对同一端点发两次请求,故合并
4262
+ * 为单次 fetch;失败返回空值(余额 []、对账 undefined),由调用方降级。
4263
+ * @returns the balances and reconcile notice (both degraded on any failure).
4248
4264
  */
4249
- async function fetchReconcile() {
4265
+ async function fetchBalanceDoc() {
4250
4266
  try {
4251
4267
  const response = await fetch(BALANCE_PATH);
4252
- if (!response.ok) return void 0;
4268
+ if (!response.ok) return { balances: [] };
4253
4269
  const text = await response.text();
4254
4270
  const parsed = JSON.parse(text);
4255
- if (parsed !== null && typeof parsed === "object" && "reconcile" in parsed) return parsed.reconcile;
4256
- return;
4271
+ if (parsed === null || typeof parsed !== "object") return { balances: [] };
4272
+ const doc = parsed;
4273
+ return {
4274
+ balances: Array.isArray(doc.balances) ? doc.balances : [],
4275
+ ...doc.reconcile === void 0 ? {} : { reconcile: doc.reconcile }
4276
+ };
4257
4277
  } catch {
4258
- return;
4278
+ return { balances: [] };
4259
4279
  }
4260
4280
  }
4261
4281
  /**
@@ -4271,20 +4291,16 @@ window.__ModuleLoader__.load({
4271
4291
  throw new Error("subscriptions: invalid response");
4272
4292
  }
4273
4293
  /**
4274
- * 拉取中转站额度(New API / Sub2API 的余额与滚动窗口);失败返回空列表。
4275
- * @returns the relay-site quota rows, or an empty list on any failure.
4294
+ * 拉取中转站额度(New API / Sub2API 的余额与滚动窗口);失败抛出(调用方据此保留旧快照)。
4295
+ * @returns the relay-site quota rows(成功但无中转配置时为空数组)。
4276
4296
  */
4277
4297
  async function fetchRelayQuotas() {
4278
- try {
4279
- const response = await fetch(RELAY_PATH);
4280
- if (!response.ok) return [];
4281
- const text = await response.text();
4282
- const parsed = JSON.parse(text);
4283
- if (parsed !== null && typeof parsed === "object" && "quotas" in parsed) return parsed.quotas;
4284
- return [];
4285
- } catch {
4286
- return [];
4287
- }
4298
+ const response = await fetch(RELAY_PATH);
4299
+ if (!response.ok) throw new Error(`relay-quotas HTTP ${String(response.status)}`);
4300
+ const text = await response.text();
4301
+ const parsed = JSON.parse(text);
4302
+ if (parsed !== null && typeof parsed === "object" && "quotas" in parsed) return parsed.quotas;
4303
+ throw new Error("relay-quotas: invalid response");
4288
4304
  }
4289
4305
  /**
4290
4306
  * 读取 usage_stats 工具开关当前值(插件自带接口,不依赖宿主浏览器设置白名单)。
@@ -4389,7 +4405,9 @@ window.__ModuleLoader__.load({
4389
4405
  " ",
4390
4406
  formatMoney(todayCost),
4391
4407
  " · ",
4392
- weekCost > 0 ? `${t("billing.weekCost")} ${formatMoney(weekCost)}` : ""
4408
+ t("billing.weekCost"),
4409
+ " ",
4410
+ formatMoney(weekCost)
4393
4411
  ]
4394
4412
  })]
4395
4413
  }),
@@ -4793,7 +4811,7 @@ window.__ModuleLoader__.load({
4793
4811
  return {
4794
4812
  pct: Number.isFinite(budgetPct) ? Math.max(0, Math.min(100, budgetPct)) : yearCost > 0 ? Math.max(0, Math.min(100, monthCost / yearCost * 100)) : 0,
4795
4813
  over: Number.isFinite(budgetPct) && budgetPct >= 100,
4796
- label: t("billing.budget")
4814
+ label: Number.isFinite(budgetPct) ? t("billing.budget") : t("billing.monthCost")
4797
4815
  };
4798
4816
  }, [
4799
4817
  budgetEnabled,
@@ -4896,9 +4914,17 @@ window.__ModuleLoader__.load({
4896
4914
  else list.push(quota);
4897
4915
  }
4898
4916
  const modelsByVendor = /* @__PURE__ */ new Map();
4917
+ const vendorByNorm = /* @__PURE__ */ new Map();
4918
+ for (const vendor of subscriptionsByVendor.keys()) vendorByNorm.set(normalizeProvider(vendor), vendor);
4899
4919
  for (const row of modelRows) {
4900
- const list = modelsByVendor.get(row.provider);
4901
- if (list === void 0) modelsByVendor.set(row.provider, [row]);
4920
+ let vendorName = row.provider;
4921
+ if (row.plan === true) {
4922
+ const inferred = providerFromModelKey(row.key);
4923
+ if (inferred !== void 0) vendorName = inferred;
4924
+ }
4925
+ const key = vendorByNorm.get(normalizeProvider(vendorName)) ?? vendorName;
4926
+ const list = modelsByVendor.get(key);
4927
+ if (list === void 0) modelsByVendor.set(key, [row]);
4902
4928
  else list.push(row);
4903
4929
  }
4904
4930
  const groups = [...new Set([...modelsByVendor.keys(), ...subscriptionsByVendor.keys()])].map((name) => ({
@@ -6487,7 +6513,6 @@ window.__ModuleLoader__.load({
6487
6513
  "data-testid": "billing-tab-panel-token",
6488
6514
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TokenPanel, {
6489
6515
  stats,
6490
- currency,
6491
6516
  trendDays,
6492
6517
  onTrendDays: setTrendDays,
6493
6518
  t
@@ -6680,11 +6705,9 @@ window.__ModuleLoader__.load({
6680
6705
  loadUsageStats().then((data) => {
6681
6706
  if (data !== null) setStats(data);
6682
6707
  });
6683
- fetchBalances().then((list) => {
6684
- if (list.length > 0) setBalances(list);
6685
- });
6686
- fetchReconcile().then((notice) => {
6687
- setReconcile(notice);
6708
+ fetchBalanceDoc().then(({ balances, reconcile }) => {
6709
+ if (balances.length > 0) setBalances(balances);
6710
+ setReconcile(reconcile);
6688
6711
  });
6689
6712
  fetchSubscriptions().then((list) => {
6690
6713
  if (list.length > 0) {
@@ -6695,8 +6718,8 @@ window.__ModuleLoader__.load({
6695
6718
  setQuotasStale(true);
6696
6719
  });
6697
6720
  fetchRelayQuotas().then((list) => {
6698
- if (list.length > 0) setRelayQuotas(list);
6699
- });
6721
+ setRelayQuotas(list);
6722
+ }).catch(() => {});
6700
6723
  }, []);
6701
6724
  const openDashboard = (0, react.useCallback)(() => {
6702
6725
  reloadStats();
@@ -6739,6 +6762,13 @@ window.__ModuleLoader__.load({
6739
6762
  const [peakConfig, setPeakConfig] = (0, react.useState)(() => loadPeakAlertConfig());
6740
6763
  const [peakHit, setPeakHit] = (0, react.useState)(null);
6741
6764
  const [peakPreview, setPeakPreview] = (0, react.useState)(null);
6765
+ const [nowMs, setNowMs] = (0, react.useState)(() => Date.now());
6766
+ (0, react.useEffect)(() => {
6767
+ const timer = setInterval(() => setNowMs(Date.now()), STATS_REFRESH_INTERVAL_MS);
6768
+ return () => {
6769
+ clearInterval(timer);
6770
+ };
6771
+ }, []);
6742
6772
  const updatePeakConfig = (0, react.useCallback)((config) => {
6743
6773
  setPeakConfig(config);
6744
6774
  savePeakAlertConfig(config);
@@ -6777,19 +6807,20 @@ window.__ModuleLoader__.load({
6777
6807
  t
6778
6808
  ]);
6779
6809
  (0, react.useEffect)(() => {
6780
- const upcoming = computePeakAlert(Date.now(), peakConfig, lastTierSwitchAt);
6810
+ const upcoming = computePeakAlert(nowMs, peakConfig, lastTierSwitchAt);
6781
6811
  if (upcoming === null) return;
6782
6812
  actions.markTierSwitchAlerted(upcoming.atMs);
6783
6813
  setPeakHit(upcoming);
6784
6814
  if (!peakConfig.webNotify) return;
6785
6815
  if (typeof Notification === "undefined" || Notification.permission !== "granted") return;
6786
- const minutes = Math.max(1, Math.round((upcoming.atMs - Date.now()) / 6e4));
6816
+ const minutes = Math.max(1, Math.round((upcoming.atMs - nowMs) / 6e4));
6787
6817
  const title = upcoming.entering === "peak" ? t("billing.peakAlertTitlePeak") : t("billing.peakAlertTitleOff");
6788
6818
  const body = upcoming.entering === "peak" ? t("billing.tierAlertEnterPeak").replace("{minutes}", String(minutes)) : t("billing.tierAlertEnterOff").replace("{minutes}", String(minutes));
6789
6819
  try {
6790
6820
  new Notification(title, { body });
6791
6821
  } catch {}
6792
6822
  }, [
6823
+ nowMs,
6793
6824
  lastTierSwitchAt,
6794
6825
  peakConfig,
6795
6826
  actions,
@@ -6904,8 +6935,7 @@ window.__ModuleLoader__.load({
6904
6935
  input: total.input,
6905
6936
  output: total.output,
6906
6937
  cacheRead: total.cacheHit,
6907
- calls: total.calls,
6908
- updatedAt: stats.updatedAt === void 0 ? void 0 : `${localDayStamp(stats.updatedAt)} ${formatClock(stats.updatedAt)}`
6938
+ calls: total.calls
6909
6939
  };
6910
6940
  }, [stats]);
6911
6941
  (0, react.useEffect)(() => {
@@ -7205,7 +7235,9 @@ window.__ModuleLoader__.load({
7205
7235
  },
7206
7236
  publishCosts: (next) => {
7207
7237
  costs = next;
7208
- for (const listener of listeners) listener(next);
7238
+ for (const listener of listeners) try {
7239
+ listener(next);
7240
+ } catch {}
7209
7241
  },
7210
7242
  registerOpen: (handler) => {
7211
7243
  open = handler;
@@ -7293,11 +7325,15 @@ window.__ModuleLoader__.load({
7293
7325
  */
7294
7326
  function installCompletionNotifier(list, getConfig) {
7295
7327
  const previousFinished = /* @__PURE__ */ new Set();
7296
- let queuedTitle;
7328
+ const seen = /* @__PURE__ */ new Set();
7329
+ let closeTimer;
7297
7330
  const snapshot = list.getSnapshot();
7298
7331
  for (const id of snapshot.ids) {
7299
7332
  const summary = snapshot.byId[id];
7300
- if (summary !== void 0 && isFinished(summary)) previousFinished.add(String(id));
7333
+ if (summary !== void 0) {
7334
+ seen.add(String(id));
7335
+ if (isFinished(summary)) previousFinished.add(String(id));
7336
+ }
7301
7337
  }
7302
7338
  const notify = (title) => {
7303
7339
  const { enabled, timeout } = getConfig();
@@ -7305,14 +7341,18 @@ window.__ModuleLoader__.load({
7305
7341
  if (typeof Notification === "undefined") return;
7306
7342
  if (Notification.permission !== "granted") return;
7307
7343
  try {
7308
- new Notification(title, {
7344
+ const notification = new Notification(title, {
7309
7345
  body: title,
7310
7346
  tag: "dsh-billing-completion",
7311
7347
  requireInteraction: timeout === 0
7312
7348
  });
7349
+ if (timeout > 0) {
7350
+ if (closeTimer !== void 0) clearTimeout(closeTimer);
7351
+ closeTimer = setTimeout(() => notification.close(), timeout * 1e3);
7352
+ }
7313
7353
  } catch {}
7314
7354
  };
7315
- return list.subscribe(() => {
7355
+ const unsubscribe = list.subscribe(() => {
7316
7356
  const state = list.getSnapshot();
7317
7357
  const finishedTitles = [];
7318
7358
  for (const id of state.ids) {
@@ -7320,15 +7360,21 @@ window.__ModuleLoader__.load({
7320
7360
  if (summary === void 0) continue;
7321
7361
  const key = String(id);
7322
7362
  const finished = isFinished(summary);
7323
- if (finished && !previousFinished.has(key)) finishedTitles.push(summary.title ?? summary.id ?? key);
7363
+ const firstSeen = !seen.has(key);
7364
+ if (firstSeen) seen.add(key);
7365
+ if (finished && !firstSeen && !previousFinished.has(key)) finishedTitles.push(summary.title ?? summary.id ?? key);
7324
7366
  if (finished) previousFinished.add(key);
7325
7367
  else previousFinished.delete(key);
7326
7368
  }
7327
7369
  if (finishedTitles.length > 0) {
7328
- queuedTitle = finishedTitles.length === 1 ? finishedTitles[0] : `${finishedTitles.length} 个会话已完成`;
7329
- if (queuedTitle !== void 0) notify(queuedTitle);
7370
+ const title = finishedTitles.length === 1 ? finishedTitles[0] : `${finishedTitles.length} 个会话已完成`;
7371
+ if (title !== void 0) notify(title);
7330
7372
  }
7331
7373
  });
7374
+ return () => {
7375
+ unsubscribe();
7376
+ if (closeTimer !== void 0) clearTimeout(closeTimer);
7377
+ };
7332
7378
  }
7333
7379
  //#endregion
7334
7380
  //#region src/client/apply.ts