opencode-go-usage-tui 1.3.1 → 1.3.3

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/dist/tui.js CHANGED
@@ -50,14 +50,14 @@ var ZH_T = {
50
50
  onboardConfigTitle: "Welcome to Go Usage / \u6B22\u8FCE\u4F7F\u7528 Go \u7528\u91CF",
51
51
  onboardConfigDesc: "First-time setup / \u9996\u6B21\u4F7F\u7528\u9700\u914D\u7F6E\u8D26\u53F7",
52
52
  setupCanceled: "\u5DF2\u53D6\u6D88\u914D\u7F6E\uFF0C\u8F93\u5165 /go-config \u53EF\u91CD\u65B0\u8BBE\u7F6E",
53
- // ── 模型价格表 ──
54
- priceTitle: "\u6A21\u578B\u4EF7\u683C",
55
- priceLoading: "\u6293\u53D6\u4EF7\u683C\u4E2D...",
56
- priceError: "\u4EF7\u683C\u6293\u53D6\u5931\u8D25",
53
+ // ── 模型限额表 ──
54
+ priceTitle: "\u6A21\u578B\u9650\u989D",
55
+ priceLoading: "\u6293\u53D6\u9650\u989D\u4E2D...",
56
+ priceError: "\u9650\u989D\u6293\u53D6\u5931\u8D25",
57
57
  priceUpdated: "\u66F4\u65B0\u65F6\u95F4",
58
- priceChanged: "\u4EF7\u683C\u6709\u53D8\u5316",
58
+ priceChanged: "\u9650\u989D\u6709\u53D8\u5316",
59
59
  priceNoChange: "\u65E0\u53D8\u5316",
60
- priceChangesSummary: "{t} \u9879\u53D8\u5316\uFF1A{a} \u65B0\u589E / {r} \u4E0B\u67B6 / {p} \u4EF7\u683C / {l} \u9650\u989D",
60
+ priceChangesSummary: "{t}\u9879\u53D8\u5316 \u65B0\u589E{a}/\u4E0B\u67B6{r}/\u9650\u989D{l}",
61
61
  priceVariantTag: "{n}\u4E2A\u6863\u4F4D",
62
62
  priceInput: "\u8F93\u5165",
63
63
  priceOutput: "\u8F93\u51FA",
@@ -68,24 +68,32 @@ var ZH_T = {
68
68
  priceReqWeek: "\u5468\u8BF7\u6C42",
69
69
  priceReqMonth: "\u6708\u8BF7\u6C42",
70
70
  priceModelCol: "\u6A21\u578B",
71
- priceReqs: "\u8BF7\u6C42\u6570(5h/\u5468/\u6708)",
71
+ priceReqs: "\u4E0A\u9650($)",
72
72
  priceSdk: "SDK",
73
73
  priceDiffUp: "\u2191{v}",
74
74
  priceDiffDown: "\u2193{v}",
75
75
  priceDiffSame: "=",
76
- priceChartTitle: "\u4EF7\u683C\u53D8\u5316\u8BB0\u5F55",
76
+ priceChartTitle: "\u9650\u989D\u53D8\u5316\u8BB0\u5F55",
77
77
  priceChartEmpty: "\u6682\u65E0\u53D8\u5316\u8BB0\u5F55",
78
78
  priceChartAdded: "\u65B0\u589E: {n}",
79
79
  priceChartChanged: "\u53D8\u5316: {n}",
80
80
  priceChartRemoved: "\u79FB\u9664: {n}",
81
- priceCollapse: "\u4EF7\u683C\u8868",
82
- priceExpand: "\u4EF7\u683C\u8868",
81
+ priceCollapse: "\u9650\u989D\u8868",
82
+ priceExpand: "\u9650\u989D\u8868",
83
+ priceRetention: "\u4FDD\u7559\u671F",
84
+ priceTraining: "\u8BAD\u7EC3",
85
+ priceTier: "\u6863\u4F4D",
86
+ changelogTitle: "\u6700\u8FD1\u53D8\u5316",
87
+ typeAdded: "\u65B0\u589E",
88
+ typeRemoved: "\u4E0B\u67B6",
89
+ typePricing: "\u4EF7\u683C",
90
+ typeLimits: "\u9650\u989D",
83
91
  settingsTitle: "Go \u7528\u91CF\u8BBE\u7F6E",
84
92
  settingsDesc: "\u5173\u6CE8\u6A21\u578B\u3001\u5237\u65B0\u95F4\u9694\u8BBE\u7F6E",
85
93
  settingsFocus: "\u5173\u6CE8\u7684\u6A21\u578B",
86
94
  settingsRefresh: "\u5237\u65B0\u95F4\u9694 (\u79D2)",
87
95
  settingsRefreshUsage: "\u7528\u91CF\u5237\u65B0\u95F4\u9694 (\u79D2)",
88
- settingsRefreshPricing: "\u4EF7\u683C\u5237\u65B0\u95F4\u9694 (\u79D2)",
96
+ settingsRefreshPricing: "\u9650\u989D\u5237\u65B0\u95F4\u9694 (\u79D2)",
89
97
  settingsSaved: "\u8BBE\u7F6E\u5DF2\u4FDD\u5B58",
90
98
  settingsCanceled: "\u5DF2\u53D6\u6D88\u8BBE\u7F6E",
91
99
  focusAll: "\u5168\u90E8\u9009\u62E9",
@@ -131,14 +139,14 @@ var EN_T = {
131
139
  onboardConfigTitle: "Welcome to Go Usage / \u6B22\u8FCE\u4F7F\u7528 Go \u7528\u91CF",
132
140
  onboardConfigDesc: "First-time setup / \u9996\u6B21\u4F7F\u7528\u9700\u914D\u7F6E\u8D26\u53F7",
133
141
  setupCanceled: "Setup canceled, run /go-config to reconfigure",
134
- // ── 模型价格表 ──
135
- priceTitle: "Model Pricing",
136
- priceLoading: "Fetching pricing...",
137
- priceError: "Pricing fetch failed",
138
- priceUpdated: "Pricing updated",
139
- priceChanged: "Pricing changed",
142
+ // ── 模型限额表 ──
143
+ priceTitle: "Model Limits",
144
+ priceLoading: "Fetching limits...",
145
+ priceError: "Limit fetch failed",
146
+ priceUpdated: "Limits updated",
147
+ priceChanged: "Limits changed",
140
148
  priceNoChange: "No changes",
141
- priceChangesSummary: "{t} change(s): {a} added / {r} removed / {p} price / {l} limit",
149
+ priceChangesSummary: "{t} changes +{a} -{r} ~{l}",
142
150
  priceVariantTag: "{n} tiers",
143
151
  priceInput: "In",
144
152
  priceOutput: "Out",
@@ -149,24 +157,32 @@ var EN_T = {
149
157
  priceReqWeek: "Wk req",
150
158
  priceReqMonth: "Mo req",
151
159
  priceModelCol: "Model",
152
- priceReqs: "Requests (5h/wk/mo)",
160
+ priceReqs: "Limit ($)",
153
161
  priceSdk: "SDK",
154
162
  priceDiffUp: "\u2191{v}",
155
163
  priceDiffDown: "\u2193{v}",
156
164
  priceDiffSame: "=",
157
- priceChartTitle: "Price change history",
165
+ priceChartTitle: "Limit change history",
158
166
  priceChartEmpty: "No change history yet",
159
167
  priceChartAdded: "Added: {n}",
160
168
  priceChartChanged: "Changed: {n}",
161
169
  priceChartRemoved: "Removed: {n}",
162
- priceCollapse: "Pricing",
163
- priceExpand: "Pricing",
170
+ priceCollapse: "Limits",
171
+ priceExpand: "Limits",
172
+ priceRetention: "Retention",
173
+ priceTraining: "Training",
174
+ priceTier: "Tier",
175
+ changelogTitle: "Recent changes",
176
+ typeAdded: "Added",
177
+ typeRemoved: "Removed",
178
+ typePricing: "Pricing",
179
+ typeLimits: "Limit",
164
180
  settingsTitle: "Go Usage Settings",
165
181
  settingsDesc: "Focused models, refresh interval settings",
166
182
  settingsFocus: "Focused models",
167
183
  settingsRefresh: "Refresh interval (sec)",
168
184
  settingsRefreshUsage: "Usage refresh interval (sec)",
169
- settingsRefreshPricing: "Pricing refresh interval (sec)",
185
+ settingsRefreshPricing: "Limit refresh interval (sec)",
170
186
  settingsSaved: "Settings saved",
171
187
  settingsCanceled: "Settings canceled",
172
188
  focusAll: "Select all",
@@ -303,7 +319,7 @@ async function fetchPricing() {
303
319
  if (!priceGroupMap.has(key)) priceGroupMap.set(key, []);
304
320
  priceGroupMap.get(key).push({ baseName, variant, row });
305
321
  }
306
- const models = [];
322
+ const modelMap = /* @__PURE__ */ new Map();
307
323
  for (const row of limitRows.slice(1)) {
308
324
  if (row.length < 4) continue;
309
325
  const name = row[0];
@@ -325,7 +341,7 @@ async function fetchPricing() {
325
341
  const allOutputs = variants.map((v) => v.pricing.output).filter((v) => v !== null);
326
342
  const allReads = variants.map((v) => v.pricing.cachedRead).filter((v) => v !== null);
327
343
  const allWrites = variants.map((v) => v.pricing.cachedWrite).filter((v) => v !== null);
328
- models.push({
344
+ const model = {
329
345
  id,
330
346
  name,
331
347
  variants,
@@ -345,8 +361,20 @@ async function fetchPricing() {
345
361
  sdk: endpointRow ? endpointRow[3] || "" : "",
346
362
  training: retentionRow ? retentionRow[1] || "" : "",
347
363
  retention: retentionRow ? retentionRow[2] || "" : ""
348
- });
364
+ };
365
+ if (modelMap.has(key)) {
366
+ const existing = modelMap.get(key);
367
+ const merged = new Map(existing.variants.map((v) => [v.label, v]));
368
+ for (const v of model.variants) if (!merged.has(v.label)) merged.set(v.label, v);
369
+ const mv = [...merged.values()];
370
+ existing.variants = mv;
371
+ if (mv.length === 1) existing.pricing = mv[0].pricing;
372
+ modelMap.set(key, existing);
373
+ } else {
374
+ modelMap.set(key, model);
375
+ }
349
376
  }
377
+ const models = [...modelMap.values()];
350
378
  return { fetchTime: (/* @__PURE__ */ new Date()).toISOString(), models };
351
379
  }
352
380
  function comparePricing(oldData, newData) {
@@ -460,7 +488,7 @@ function updatePricingStore(newData) {
460
488
  }
461
489
 
462
490
  // src/index.tsx
463
- var VERSION = "1.3.1";
491
+ var VERSION = "1.3.3";
464
492
  var CHECK_INTERVAL = Number(process?.env?.OPENCODE_GO_CHECK_INTERVAL ?? 6e4);
465
493
  var WARN_THRESHOLD = Number(process?.env?.OPENCODE_GO_WARN_THRESHOLD ?? 0.8);
466
494
  var CONFIG_DIR = process?.env?.OPENCODE_CONFIG_DIR || (process?.env?.USERPROFILE ? `${process.env.USERPROFILE}\\.config\\opencode` : "") || process?.env?.HOME + "/.config/opencode";
@@ -931,7 +959,11 @@ function GoUsagePanel(props) {
931
959
  _$insertNode(_el$10, _el$11);
932
960
  _$insertNode(_el$10, _el$12);
933
961
  _$insertNode(_el$10, _el$14);
934
- _$setProp(_el$10, "onMouseUp", () => setOpen((o) => !o));
962
+ _$setProp(_el$10, "selectable", false);
963
+ _$setProp(_el$10, "onMouseUp", (e) => {
964
+ e.preventDefault();
965
+ setOpen((o) => !o);
966
+ });
935
967
  _$insert(_el$11, () => open() ? "\u25BC " : "\u25B6 ");
936
968
  _$insertNode(_el$12, _el$13);
937
969
  _$insert(_el$13, () => t("panelTitle"));
@@ -1073,6 +1105,30 @@ function PricePanel(props) {
1073
1105
  const [priceError, setPriceError] = createSignal("");
1074
1106
  const [priceLoading, setPriceLoading] = createSignal(false);
1075
1107
  const [panelWidth, setPanelWidth] = createSignal(24);
1108
+ const [renderTick, setRenderTick] = createSignal(0);
1109
+ const [listReady, setListReady] = createSignal(false);
1110
+ createEffect(() => {
1111
+ const p = sharedPricing();
1112
+ if (p && p.models.length > 0) {
1113
+ const id = setTimeout(() => setListReady(true), 150);
1114
+ onCleanup(() => clearTimeout(id));
1115
+ } else {
1116
+ setListReady(false);
1117
+ }
1118
+ });
1119
+ createEffect(() => {
1120
+ if (!(listReady() && sharedPricing())) return;
1121
+ const t1 = setTimeout(() => setRenderTick((v) => v + 1), 250);
1122
+ const t2 = setTimeout(() => setRenderTick((v) => v + 1), 600);
1123
+ const t3 = setTimeout(() => setRenderTick((v) => v + 1), 1e3);
1124
+ onCleanup(() => {
1125
+ clearTimeout(t1);
1126
+ clearTimeout(t2);
1127
+ clearTimeout(t3);
1128
+ });
1129
+ });
1130
+ const [changedModels, setChangedModels] = createSignal(/* @__PURE__ */ new Map());
1131
+ const [expandedId, setExpandedId] = createSignal(null);
1076
1132
  const [cfg, setCfg] = createSignal(loadConfig());
1077
1133
  createEffect(() => {
1078
1134
  void configTick();
@@ -1080,10 +1136,23 @@ function PricePanel(props) {
1080
1136
  });
1081
1137
  let boxEl;
1082
1138
  let priceController = null;
1083
- createEffect(() => {
1084
- if (boxEl && typeof boxEl.width === "number" && boxEl.width > 0) {
1085
- setPanelWidth(Math.max(20, boxEl.width));
1086
- }
1139
+ let widthSyncTimer = null;
1140
+ onMount(() => {
1141
+ let tries = 0;
1142
+ const syncWidth = () => {
1143
+ tries++;
1144
+ if (boxEl && typeof boxEl.width === "number" && boxEl.width > 0) {
1145
+ setPanelWidth(Math.max(20, boxEl.width));
1146
+ setRenderTick((v) => v + 1);
1147
+ widthSyncTimer = setTimeout(() => setRenderTick((v) => v + 1), 150);
1148
+ return;
1149
+ }
1150
+ if (tries < 50) widthSyncTimer = setTimeout(syncWidth, 80);
1151
+ };
1152
+ widthSyncTimer = setTimeout(syncWidth, 30);
1153
+ });
1154
+ onCleanup(() => {
1155
+ if (widthSyncTimer) clearTimeout(widthSyncTimer);
1087
1156
  });
1088
1157
  async function refreshPricing() {
1089
1158
  if (priceLoading()) return;
@@ -1100,6 +1169,14 @@ function PricePanel(props) {
1100
1169
  if (prev && prev.fetchTime !== data.fetchTime) {
1101
1170
  const diff = comparePricing(prev, data);
1102
1171
  if (diff.hasChanges) {
1172
+ const m = /* @__PURE__ */ new Map();
1173
+ for (const c of diff.changes) {
1174
+ if (c.type === "removed") continue;
1175
+ const cat = c.type === "added" ? "added" : c.type === "pricing" ? "pricing" : "limits";
1176
+ if (!m.has(c.modelId)) m.set(c.modelId, /* @__PURE__ */ new Set());
1177
+ m.get(c.modelId).add(cat);
1178
+ }
1179
+ setChangedModels(m);
1103
1180
  props.api.toast({
1104
1181
  variant: "info",
1105
1182
  title: t("priceChanged"),
@@ -1107,11 +1184,14 @@ function PricePanel(props) {
1107
1184
  t: diff.summary.total,
1108
1185
  a: diff.summary.added,
1109
1186
  r: diff.summary.removed,
1110
- p: diff.summary.priceChanges,
1111
1187
  l: diff.summary.limitChanges
1112
1188
  })
1113
1189
  });
1190
+ } else {
1191
+ setChangedModels(/* @__PURE__ */ new Map());
1114
1192
  }
1193
+ } else {
1194
+ setChangedModels(/* @__PURE__ */ new Map());
1115
1195
  }
1116
1196
  } catch {
1117
1197
  setPriceError(t("priceError"));
@@ -1120,10 +1200,6 @@ function PricePanel(props) {
1120
1200
  priceController = null;
1121
1201
  }
1122
1202
  }
1123
- function formatCount(n) {
1124
- if (n >= 1e3) return (n / 1e3).toFixed(1).replace(/\.0$/, "") + "k";
1125
- return String(n);
1126
- }
1127
1203
  function visualPadEnd(s, w) {
1128
1204
  const cur = visualWidth(s);
1129
1205
  if (cur >= w) return s;
@@ -1142,6 +1218,7 @@ function PricePanel(props) {
1142
1218
  return out + "\u2026";
1143
1219
  }
1144
1220
  function justify(label, value) {
1221
+ void renderTick();
1145
1222
  const outer = boxEl && typeof boxEl.width === "number" && boxEl.width > 0 ? boxEl.width : panelWidth();
1146
1223
  const gauge = Math.max(10, outer - 4);
1147
1224
  const used = visualWidth(label) + visualWidth(value);
@@ -1149,17 +1226,91 @@ function PricePanel(props) {
1149
1226
  return label + " ".repeat(gap) + value;
1150
1227
  }
1151
1228
  function renderLimitRow(m) {
1229
+ const cats = changedModels().get(m.id);
1230
+ const expanded = expandedId() === m.id;
1152
1231
  const name = abbreviateName(m.name, 18);
1153
- const req = `${formatCount(m.limits.fiveHour)}/${formatCount(m.limits.weekly)}/${formatCount(m.limits.monthly)}`;
1154
- return (() => {
1155
- var _el$30 = _$createElement("text"), _el$31 = _$createElement("span");
1156
- _$insertNode(_el$30, _el$31);
1157
- _$insert(_el$31, () => justify(name, req));
1158
- _$effect((_$p) => _$setProp(_el$31, "style", {
1159
- fg: colors().text
1160
- }, _$p));
1232
+ const req = m.usageLimit != null ? `$${m.usageLimit}` : "\u2014";
1233
+ const fg = cats?.has("added") ? colors().success : cats?.has("pricing") ? colors().primary : cats?.has("limits") ? colors().warning : colors().text;
1234
+ const ind = expanded ? " \u25BE" : " \u25B8";
1235
+ const row = (() => {
1236
+ var _el$30 = _$createElement("text");
1237
+ _$setProp(_el$30, "fg", fg);
1238
+ _$setProp(_el$30, "onMouseUp", (e) => {
1239
+ e.preventDefault();
1240
+ setExpandedId(expanded ? null : m.id);
1241
+ });
1242
+ _$insert(_el$30, () => justify(name, req + ind));
1161
1243
  return _el$30;
1162
1244
  })();
1245
+ if (!expanded) return row;
1246
+ return [row, _$memo(() => renderPriceDetail(m))];
1247
+ }
1248
+ function renderPriceDetail(m) {
1249
+ const prev = pricingStore()?.previous?.models.find((x) => x.id === m.id);
1250
+ const prevVariants = prev?.variants;
1251
+ const arrow = (cur, old) => {
1252
+ if (old == null || cur == null || old === cur) return "";
1253
+ return cur > old ? " \u2191" : " \u2193";
1254
+ };
1255
+ const fmt = (cur, old) => cur == null ? "-" : `$${cur} /MTok${arrow(cur, old)}`;
1256
+ const pad13 = (s) => visualPadEnd(s, 13);
1257
+ const lines = [];
1258
+ const tiers = m.variants;
1259
+ const hasTiers = tiers.length > 1;
1260
+ if (hasTiers) {
1261
+ tiers.forEach((v, ti) => {
1262
+ const isLastTier = ti === tiers.length - 1;
1263
+ lines.push((() => {
1264
+ var _el$31 = _$createElement("text");
1265
+ _$insert(_el$31, () => ` \u251C ${t("priceTier")}: ${v.label}`);
1266
+ _$effect((_$p) => _$setProp(_el$31, "fg", colors().muted, _$p));
1267
+ return _el$31;
1268
+ })());
1269
+ const inner = isLastTier ? " " : "\u2502";
1270
+ const prevV = prevVariants?.find((p) => p.label === v.label) ?? prevVariants?.[ti];
1271
+ const fields = [[t("priceInput"), fmt(v.pricing.input, prevV?.pricing.input)], [t("priceOutput"), fmt(v.pricing.output, prevV?.pricing.output)], [t("priceCacheRead"), fmt(v.pricing.cachedRead, prevV?.pricing.cachedRead)], [t("priceCacheWrite"), fmt(v.pricing.cachedWrite, prevV?.pricing.cachedWrite)]];
1272
+ for (const [fl, fv] of fields) {
1273
+ lines.push((() => {
1274
+ var _el$32 = _$createElement("text");
1275
+ _$insert(_el$32, () => pad13(` ${inner} ${fl}:`) + fv);
1276
+ _$effect((_$p) => _$setProp(_el$32, "fg", colors().muted, _$p));
1277
+ return _el$32;
1278
+ })());
1279
+ }
1280
+ });
1281
+ } else {
1282
+ const v = tiers[0];
1283
+ const fields = [[t("priceInput"), fmt(v.pricing.input, prev?.pricing.input)], [t("priceOutput"), fmt(v.pricing.output, prev?.pricing.output)], [t("priceCacheRead"), fmt(v.pricing.cachedRead, prev?.pricing.cachedRead)], [t("priceCacheWrite"), fmt(v.pricing.cachedWrite, prev?.pricing.cachedWrite)]];
1284
+ for (const [fl, fv] of fields) {
1285
+ lines.push((() => {
1286
+ var _el$33 = _$createElement("text");
1287
+ _$insert(_el$33, () => pad13(` \u251C ${fl}:`) + fv);
1288
+ _$effect((_$p) => _$setProp(_el$33, "fg", colors().muted, _$p));
1289
+ return _el$33;
1290
+ })());
1291
+ }
1292
+ }
1293
+ const fmtFull = (n) => n > 0 ? n.toLocaleString("en-US") : "\u2014";
1294
+ const limitFields = [[t("priceReq5h"), fmtFull(m.limits.fiveHour)], [t("priceReqWeek"), fmtFull(m.limits.weekly)], [t("priceReqMonth"), fmtFull(m.limits.monthly)]];
1295
+ for (const [fl, fv] of limitFields) {
1296
+ lines.push((() => {
1297
+ var _el$34 = _$createElement("text");
1298
+ _$insert(_el$34, () => pad13(` \u251C ${fl}:`) + fv);
1299
+ _$effect((_$p) => _$setProp(_el$34, "fg", colors().muted, _$p));
1300
+ return _el$34;
1301
+ })());
1302
+ }
1303
+ const meta = [[t("priceSdk"), m.sdk || "-"], [t("priceRetention"), m.retention || "-"], [t("priceTraining"), m.training || "-"]];
1304
+ meta.forEach(([ml, mv], i) => {
1305
+ const conn = i < meta.length - 1 ? "\u251C" : "\u2514";
1306
+ lines.push((() => {
1307
+ var _el$35 = _$createElement("text");
1308
+ _$insert(_el$35, () => pad13(` ${conn} ${ml}:`) + mv);
1309
+ _$effect((_$p) => _$setProp(_el$35, "fg", colors().muted, _$p));
1310
+ return _el$35;
1311
+ })());
1312
+ });
1313
+ return lines;
1163
1314
  }
1164
1315
  const [pal, setPal] = createSignal({
1165
1316
  ...FALLBACK
@@ -1177,6 +1328,7 @@ function PricePanel(props) {
1177
1328
  });
1178
1329
  const colors = () => pal();
1179
1330
  const sep = () => {
1331
+ void renderTick();
1180
1332
  const outer = boxEl && typeof boxEl.width === "number" && boxEl.width > 0 ? boxEl.width : panelWidth();
1181
1333
  return "\u2500".repeat(Math.max(1, outer - 4));
1182
1334
  };
@@ -1190,60 +1342,61 @@ function PricePanel(props) {
1190
1342
  setInterval(() => refreshPricing(), loadConfig().pricingIntervalMs);
1191
1343
  }, 2e3);
1192
1344
  return (() => {
1193
- var _el$32 = _$createElement("box"), _el$33 = _$createElement("text"), _el$34 = _$createElement("span"), _el$35 = _$createElement("span"), _el$36 = _$createElement("b"), _el$40 = _$createElement("span");
1194
- _$insertNode(_el$32, _el$33);
1345
+ var _el$36 = _$createElement("box"), _el$37 = _$createElement("text"), _el$38 = _$createElement("span"), _el$39 = _$createElement("span"), _el$40 = _$createElement("b"), _el$44 = _$createElement("span");
1346
+ _$insertNode(_el$36, _el$37);
1195
1347
  var _ref$2 = boxEl;
1196
- typeof _ref$2 === "function" ? _$use(_ref$2, _el$32) : boxEl = _el$32;
1197
- _$setProp(_el$32, "border", true);
1198
- _$setProp(_el$32, "paddingLeft", 1);
1199
- _$setProp(_el$32, "paddingRight", 1);
1200
- _$setProp(_el$32, "flexDirection", "column");
1201
- _$setProp(_el$32, "gap", 0);
1202
- _$setProp(_el$32, "onSizeChange", () => {
1348
+ typeof _ref$2 === "function" ? _$use(_ref$2, _el$36) : boxEl = _el$36;
1349
+ _$setProp(_el$36, "border", true);
1350
+ _$setProp(_el$36, "paddingLeft", 1);
1351
+ _$setProp(_el$36, "paddingRight", 1);
1352
+ _$setProp(_el$36, "flexDirection", "column");
1353
+ _$setProp(_el$36, "gap", 0);
1354
+ _$setProp(_el$36, "onSizeChange", () => {
1203
1355
  if (resizeTimeout) clearTimeout(resizeTimeout);
1204
1356
  resizeTimeout = setTimeout(() => {
1205
1357
  const w = boxEl ? Math.max(20, boxEl.width ?? 24) : 24;
1206
1358
  setPanelWidth(w);
1359
+ setRenderTick((v) => v + 1);
1207
1360
  }, 100);
1208
1361
  });
1209
- _$insertNode(_el$33, _el$34);
1210
- _$insertNode(_el$33, _el$35);
1211
- _$insertNode(_el$33, _el$40);
1212
- _$setProp(_el$33, "onMouseUp", () => setOpen((o) => !o));
1213
- _$insert(_el$34, () => open() ? "\u25BC " : "\u25B6 ");
1214
- _$insertNode(_el$35, _el$36);
1215
- _$insert(_el$36, () => t("priceTitle"));
1216
- _$insert(_el$33, _$createComponent(Show, {
1362
+ _$insertNode(_el$37, _el$38);
1363
+ _$insertNode(_el$37, _el$39);
1364
+ _$insertNode(_el$37, _el$44);
1365
+ _$setProp(_el$37, "onMouseUp", () => setOpen((o) => !o));
1366
+ _$insert(_el$38, () => open() ? "\u25BC " : "\u25B6 ");
1367
+ _$insertNode(_el$39, _el$40);
1368
+ _$insert(_el$40, () => t("priceTitle"));
1369
+ _$insert(_el$37, _$createComponent(Show, {
1217
1370
  get when() {
1218
1371
  return sharedPricing();
1219
1372
  },
1220
1373
  get children() {
1221
- var _el$37 = _$createElement("span"), _el$38 = _$createTextNode(` (`), _el$39 = _$createTextNode(`)`);
1222
- _$insertNode(_el$37, _el$38);
1223
- _$insertNode(_el$37, _el$39);
1224
- _$insert(_el$37, () => sharedPricing().models.length, _el$39);
1225
- _$effect((_$p) => _$setProp(_el$37, "style", {
1374
+ var _el$41 = _$createElement("span"), _el$42 = _$createTextNode(` (`), _el$43 = _$createTextNode(`)`);
1375
+ _$insertNode(_el$41, _el$42);
1376
+ _$insertNode(_el$41, _el$43);
1377
+ _$insert(_el$41, () => sharedPricing().models.length, _el$43);
1378
+ _$effect((_$p) => _$setProp(_el$41, "style", {
1226
1379
  fg: colors().muted
1227
1380
  }, _$p));
1228
- return _el$37;
1381
+ return _el$41;
1229
1382
  }
1230
- }), _el$40);
1231
- _$insert(_el$40, () => sep().slice(visualWidth((open() ? "\u25BC " : "\u25B6 ") + t("priceTitle") + (sharedPricing() ? ` (${sharedPricing().models.length})` : ""))));
1232
- _$insert(_el$32, _$createComponent(Show, {
1383
+ }), _el$44);
1384
+ _$insert(_el$44, () => sep().slice(visualWidth((open() ? "\u25BC " : "\u25B6 ") + t("priceTitle") + (sharedPricing() ? ` (${sharedPricing().models.length})` : ""))));
1385
+ _$insert(_el$36, _$createComponent(Show, {
1233
1386
  get when() {
1234
1387
  return open();
1235
1388
  },
1236
1389
  get children() {
1237
1390
  return [(() => {
1238
- var _el$41 = _$createElement("text");
1239
- _$insert(_el$41, () => justify(t("priceModelCol"), t("priceReqs")));
1240
- _$effect((_$p) => _$setProp(_el$41, "fg", colors().muted, _$p));
1241
- return _el$41;
1391
+ var _el$45 = _$createElement("text");
1392
+ _$insert(_el$45, () => justify(t("priceModelCol"), t("priceReqs")));
1393
+ _$effect((_$p) => _$setProp(_el$45, "fg", colors().muted, _$p));
1394
+ return _el$45;
1242
1395
  })(), (() => {
1243
- var _el$42 = _$createElement("text");
1244
- _$insert(_el$42, sep);
1245
- _$effect((_$p) => _$setProp(_el$42, "fg", colors().muted, _$p));
1246
- return _el$42;
1396
+ var _el$46 = _$createElement("text");
1397
+ _$insert(_el$46, sep);
1398
+ _$effect((_$p) => _$setProp(_el$46, "fg", colors().muted, _$p));
1399
+ return _el$46;
1247
1400
  })(), _$createComponent(Show, {
1248
1401
  get when() {
1249
1402
  return priceLoading() || !sharedPricing();
@@ -1255,45 +1408,75 @@ function PricePanel(props) {
1255
1408
  },
1256
1409
  get fallback() {
1257
1410
  return (() => {
1258
- var _el$46 = _$createElement("text");
1259
- _$insert(_el$46, () => t("priceLoading"));
1260
- _$effect((_$p) => _$setProp(_el$46, "fg", colors().muted, _$p));
1261
- return _el$46;
1411
+ var _el$53 = _$createElement("text");
1412
+ _$insert(_el$53, () => t("priceLoading"));
1413
+ _$effect((_$p) => _$setProp(_el$53, "fg", colors().muted, _$p));
1414
+ return _el$53;
1262
1415
  })();
1263
1416
  },
1264
1417
  get children() {
1265
- return [_$memo(() => sharedPricing().models.filter((m) => {
1418
+ return [_$memo(() => _$memo(() => !!listReady())() ? sharedPricing().models.filter((m) => {
1266
1419
  return cfg().focusModels.length === 0 || cfg().focusModels.includes(m.id);
1267
- }).map((m) => renderLimitRow(m))), (() => {
1268
- var _el$44 = _$createElement("text");
1269
- _$insert(_el$44, () => justify(t("priceUpdated"), new Date(sharedPricing().fetchTime).toLocaleTimeString()));
1270
- _$effect((_$p) => _$setProp(_el$44, "fg", colors().muted, _$p));
1271
- return _el$44;
1420
+ }).map((m) => renderLimitRow(m)) : null), (() => {
1421
+ var _el$48 = _$createElement("text");
1422
+ _$insert(_el$48, () => justify(t("priceUpdated"), new Date(sharedPricing().fetchTime).toLocaleTimeString()));
1423
+ _$effect((_$p) => _$setProp(_el$48, "fg", colors().muted, _$p));
1424
+ return _el$48;
1272
1425
  })(), _$createComponent(Show, {
1273
1426
  get when() {
1274
1427
  return _$memo(() => !!pricingStore())() && pricingStore().history.length > 0;
1275
1428
  },
1276
1429
  get children() {
1277
- var _el$45 = _$createElement("text");
1278
- _$insert(_el$45, () => t("priceChangesSummary", {
1430
+ var _el$49 = _$createElement("text");
1431
+ _$insert(_el$49, () => t("priceChangesSummary", {
1279
1432
  t: pricingStore().history[0].summary.total,
1280
1433
  a: pricingStore().history[0].summary.added,
1281
1434
  r: pricingStore().history[0].summary.removed,
1282
- p: pricingStore().history[0].summary.priceChanges,
1283
1435
  l: pricingStore().history[0].summary.limitChanges
1284
1436
  }));
1285
- _$effect((_$p) => _$setProp(_el$45, "fg", colors().warning, _$p));
1286
- return _el$45;
1437
+ _$effect((_$p) => _$setProp(_el$49, "fg", colors().warning, _$p));
1438
+ return _el$49;
1439
+ }
1440
+ }), _$createComponent(Show, {
1441
+ get when() {
1442
+ return changedModels().size > 0;
1443
+ },
1444
+ get children() {
1445
+ var _el$50 = _$createElement("text");
1446
+ _$insertNode(_el$50, _$createTextNode(`\u7EFF=\u65B0\u589E \u84DD=\u4EF7\u683C \u6A59=\u9650\u989D\xB7\u70B9\u51FB\u5C55\u5F00`));
1447
+ _$effect((_$p) => _$setProp(_el$50, "fg", colors().muted, _$p));
1448
+ return _el$50;
1449
+ }
1450
+ }), _$createComponent(Show, {
1451
+ get when() {
1452
+ return _$memo(() => !!(pricingStore() && pricingStore().history.length > 0))() && pricingStore().history[0].summary.total > 0;
1453
+ },
1454
+ get children() {
1455
+ return [(() => {
1456
+ var _el$52 = _$createElement("text");
1457
+ _$insert(_el$52, () => `${t("changelogTitle")} (${new Date(pricingStore().history[0].fetchTime).toLocaleTimeString()})`);
1458
+ _$effect((_$p) => _$setProp(_el$52, "fg", colors().muted, _$p));
1459
+ return _el$52;
1460
+ })(), _$memo(() => pricingStore().history[0].changes.slice(0, 12).map((c) => {
1461
+ const label = c.type === "added" ? t("typeAdded") : c.type === "removed" ? t("typeRemoved") : c.type === "pricing" ? t("typePricing") : t("typeLimits");
1462
+ const fg = c.type === "added" ? colors().success : c.type === "removed" ? colors().error : c.type === "pricing" ? colors().primary : colors().warning;
1463
+ return (() => {
1464
+ var _el$54 = _$createElement("text");
1465
+ _$setProp(_el$54, "fg", fg);
1466
+ _$insert(_el$54, () => ` ${label} ${abbreviateName(c.modelName, 20)}`);
1467
+ return _el$54;
1468
+ })();
1469
+ }))];
1287
1470
  }
1288
1471
  })];
1289
1472
  }
1290
1473
  });
1291
1474
  },
1292
1475
  get children() {
1293
- var _el$43 = _$createElement("text");
1294
- _$insert(_el$43, () => t("priceLoading"));
1295
- _$effect((_$p) => _$setProp(_el$43, "fg", colors().muted, _$p));
1296
- return _el$43;
1476
+ var _el$47 = _$createElement("text");
1477
+ _$insert(_el$47, () => t("priceLoading"));
1478
+ _$effect((_$p) => _$setProp(_el$47, "fg", colors().muted, _$p));
1479
+ return _el$47;
1297
1480
  }
1298
1481
  })];
1299
1482
  }
@@ -1306,10 +1489,10 @@ function PricePanel(props) {
1306
1489
  }, _v$12 = {
1307
1490
  fg: colors().muted
1308
1491
  };
1309
- _v$1 !== _p$.e && (_p$.e = _$setProp(_el$32, "borderColor", _v$1, _p$.e));
1310
- _v$10 !== _p$.t && (_p$.t = _$setProp(_el$34, "style", _v$10, _p$.t));
1311
- _v$11 !== _p$.a && (_p$.a = _$setProp(_el$35, "style", _v$11, _p$.a));
1312
- _v$12 !== _p$.o && (_p$.o = _$setProp(_el$40, "style", _v$12, _p$.o));
1492
+ _v$1 !== _p$.e && (_p$.e = _$setProp(_el$36, "borderColor", _v$1, _p$.e));
1493
+ _v$10 !== _p$.t && (_p$.t = _$setProp(_el$38, "style", _v$10, _p$.t));
1494
+ _v$11 !== _p$.a && (_p$.a = _$setProp(_el$39, "style", _v$11, _p$.a));
1495
+ _v$12 !== _p$.o && (_p$.o = _$setProp(_el$44, "style", _v$12, _p$.o));
1313
1496
  return _p$;
1314
1497
  }, {
1315
1498
  e: void 0,
@@ -1317,7 +1500,7 @@ function PricePanel(props) {
1317
1500
  a: void 0,
1318
1501
  o: void 0
1319
1502
  });
1320
- return _el$32;
1503
+ return _el$36;
1321
1504
  })();
1322
1505
  }
1323
1506
  function createSidebarSlot(api) {
@@ -1356,9 +1539,9 @@ function runConfigDialog(api, dialog) {
1356
1539
  return t("wsPromptTitle");
1357
1540
  },
1358
1541
  description: () => (() => {
1359
- var _el$47 = _$createElement("text");
1360
- _$insert(_el$47, () => t("wsPromptDesc"));
1361
- return _el$47;
1542
+ var _el$55 = _$createElement("text");
1543
+ _$insert(_el$55, () => t("wsPromptDesc"));
1544
+ return _el$55;
1362
1545
  })(),
1363
1546
  get placeholder() {
1364
1547
  return t("wsPlaceholder");
@@ -1377,9 +1560,9 @@ function runConfigDialog(api, dialog) {
1377
1560
  return t("cookiePromptTitle");
1378
1561
  },
1379
1562
  description: () => (() => {
1380
- var _el$48 = _$createElement("text");
1381
- _$insert(_el$48, () => t("cookiePromptDesc"));
1382
- return _el$48;
1563
+ var _el$56 = _$createElement("text");
1564
+ _$insert(_el$56, () => t("cookiePromptDesc"));
1565
+ return _el$56;
1383
1566
  })(),
1384
1567
  get placeholder() {
1385
1568
  return t("cookiePlaceholder");
@@ -1527,9 +1710,9 @@ function runSettingsDialog(api, dialog) {
1527
1710
  return t("settingsRefreshUsage");
1528
1711
  },
1529
1712
  description: () => (() => {
1530
- var _el$49 = _$createElement("text");
1531
- _$insertNode(_el$49, _$createTextNode(`\u8F93\u5165\u79D2\u6570\uFF08\u9ED8\u8BA4 60\uFF09`));
1532
- return _el$49;
1713
+ var _el$57 = _$createElement("text");
1714
+ _$insertNode(_el$57, _$createTextNode(`\u8F93\u5165\u79D2\u6570\uFF08\u9ED8\u8BA4 60\uFF09`));
1715
+ return _el$57;
1533
1716
  })(),
1534
1717
  placeholder: "60",
1535
1718
  onConfirm: (val) => {
@@ -1556,9 +1739,9 @@ function runSettingsDialog(api, dialog) {
1556
1739
  return t("settingsRefreshPricing");
1557
1740
  },
1558
1741
  description: () => (() => {
1559
- var _el$51 = _$createElement("text");
1560
- _$insertNode(_el$51, _$createTextNode(`\u8F93\u5165\u79D2\u6570\uFF08\u9ED8\u8BA4 1800\uFF09`));
1561
- return _el$51;
1742
+ var _el$59 = _$createElement("text");
1743
+ _$insertNode(_el$59, _$createTextNode(`\u8F93\u5165\u79D2\u6570\uFF08\u9ED8\u8BA4 1800\uFF09`));
1744
+ return _el$59;
1562
1745
  })(),
1563
1746
  placeholder: "1800",
1564
1747
  onConfirm: (val) => {