opencode-go-usage-tui 1.3.0 → 1.3.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/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.0";
491
+ var VERSION = "1.3.2";
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";
@@ -692,7 +720,7 @@ async function fetchUsage(workspaceId, authCookie, signal) {
692
720
  };
693
721
  }
694
722
  const extract = (key) => {
695
- const m = text.match(new RegExp(`${key}:[^}]*?\\{status:"ok",resetInSec:(\\d+),usagePercent:(\\d+)\\}`));
723
+ const m = text.match(new RegExp(`${key}:[^}]*?\\{status:"[^"]*",resetInSec:(\\d+),usagePercent:(\\d+)\\}`));
696
724
  if (!m) return null;
697
725
  return {
698
726
  resetInSec: Number(m[1]),
@@ -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,9 @@ 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 [changedModels, setChangedModels] = createSignal(/* @__PURE__ */ new Map());
1109
+ const [expandedId, setExpandedId] = createSignal(null);
1110
+ const [mounted, setMounted] = createSignal(false);
1076
1111
  const [cfg, setCfg] = createSignal(loadConfig());
1077
1112
  createEffect(() => {
1078
1113
  void configTick();
@@ -1080,6 +1115,15 @@ function PricePanel(props) {
1080
1115
  });
1081
1116
  let boxEl;
1082
1117
  let priceController = null;
1118
+ onMount(() => {
1119
+ setTimeout(() => setMounted(true), 100);
1120
+ });
1121
+ createEffect(() => {
1122
+ mounted();
1123
+ if (boxEl && typeof boxEl.width === "number" && boxEl.width > 0) {
1124
+ setPanelWidth(Math.max(20, boxEl.width));
1125
+ }
1126
+ });
1083
1127
  async function refreshPricing() {
1084
1128
  if (priceLoading()) return;
1085
1129
  setPriceLoading(true);
@@ -1095,6 +1139,14 @@ function PricePanel(props) {
1095
1139
  if (prev && prev.fetchTime !== data.fetchTime) {
1096
1140
  const diff = comparePricing(prev, data);
1097
1141
  if (diff.hasChanges) {
1142
+ const m = /* @__PURE__ */ new Map();
1143
+ for (const c of diff.changes) {
1144
+ if (c.type === "removed") continue;
1145
+ const cat = c.type === "added" ? "added" : c.type === "pricing" ? "pricing" : "limits";
1146
+ if (!m.has(c.modelId)) m.set(c.modelId, /* @__PURE__ */ new Set());
1147
+ m.get(c.modelId).add(cat);
1148
+ }
1149
+ setChangedModels(m);
1098
1150
  props.api.toast({
1099
1151
  variant: "info",
1100
1152
  title: t("priceChanged"),
@@ -1102,11 +1154,14 @@ function PricePanel(props) {
1102
1154
  t: diff.summary.total,
1103
1155
  a: diff.summary.added,
1104
1156
  r: diff.summary.removed,
1105
- p: diff.summary.priceChanges,
1106
1157
  l: diff.summary.limitChanges
1107
1158
  })
1108
1159
  });
1160
+ } else {
1161
+ setChangedModels(/* @__PURE__ */ new Map());
1109
1162
  }
1163
+ } else {
1164
+ setChangedModels(/* @__PURE__ */ new Map());
1110
1165
  }
1111
1166
  } catch {
1112
1167
  setPriceError(t("priceError"));
@@ -1115,10 +1170,6 @@ function PricePanel(props) {
1115
1170
  priceController = null;
1116
1171
  }
1117
1172
  }
1118
- function formatCount(n) {
1119
- if (n >= 1e3) return (n / 1e3).toFixed(1).replace(/\.0$/, "") + "k";
1120
- return String(n);
1121
- }
1122
1173
  function visualPadEnd(s, w) {
1123
1174
  const cur = visualWidth(s);
1124
1175
  if (cur >= w) return s;
@@ -1137,23 +1188,99 @@ function PricePanel(props) {
1137
1188
  return out + "\u2026";
1138
1189
  }
1139
1190
  function justify(label, value) {
1140
- const gauge = panelWidth() - 4;
1191
+ const outer = boxEl && typeof boxEl.width === "number" && boxEl.width > 0 ? boxEl.width : panelWidth();
1192
+ const gauge = Math.max(10, outer - 4);
1141
1193
  const used = visualWidth(label) + visualWidth(value);
1142
1194
  const gap = Math.max(1, gauge - used);
1143
1195
  return label + " ".repeat(gap) + value;
1144
1196
  }
1145
1197
  function renderLimitRow(m) {
1198
+ const cats = changedModels().get(m.id);
1199
+ const expanded = expandedId() === m.id;
1146
1200
  const name = abbreviateName(m.name, 18);
1147
- const req = `${formatCount(m.limits.fiveHour)}/${formatCount(m.limits.weekly)}/${formatCount(m.limits.monthly)}`;
1148
- return (() => {
1149
- var _el$30 = _$createElement("text"), _el$31 = _$createElement("span");
1150
- _$insertNode(_el$30, _el$31);
1151
- _$insert(_el$31, () => justify(name, req));
1152
- _$effect((_$p) => _$setProp(_el$31, "style", {
1153
- fg: colors().text
1154
- }, _$p));
1201
+ const req = m.usageLimit != null ? `$${m.usageLimit}` : "\u2014";
1202
+ const fg = cats?.has("added") ? colors().success : cats?.has("pricing") ? colors().primary : cats?.has("limits") ? colors().warning : colors().text;
1203
+ const ind = expanded ? " \u25BE" : " \u25B8";
1204
+ const row = (() => {
1205
+ var _el$30 = _$createElement("text");
1206
+ _$setProp(_el$30, "fg", fg);
1207
+ _$setProp(_el$30, "selectable", false);
1208
+ _$setProp(_el$30, "onMouseUp", (e) => {
1209
+ e.preventDefault();
1210
+ setExpandedId(expanded ? null : m.id);
1211
+ });
1212
+ _$insert(_el$30, () => justify(name, req + ind));
1155
1213
  return _el$30;
1156
1214
  })();
1215
+ if (!expanded) return row;
1216
+ return [row, _$memo(() => renderPriceDetail(m))];
1217
+ }
1218
+ function renderPriceDetail(m) {
1219
+ const prev = pricingStore()?.previous?.models.find((x) => x.id === m.id);
1220
+ const prevVariants = prev?.variants;
1221
+ const arrow = (cur, old) => {
1222
+ if (old == null || cur == null || old === cur) return "";
1223
+ return cur > old ? " \u2191" : " \u2193";
1224
+ };
1225
+ const fmt = (cur, old) => cur == null ? "-" : `$${cur} /MTok${arrow(cur, old)}`;
1226
+ const pad13 = (s) => visualPadEnd(s, 13);
1227
+ const lines = [];
1228
+ const tiers = m.variants;
1229
+ const hasTiers = tiers.length > 1;
1230
+ if (hasTiers) {
1231
+ tiers.forEach((v, ti) => {
1232
+ const isLastTier = ti === tiers.length - 1;
1233
+ lines.push((() => {
1234
+ var _el$31 = _$createElement("text");
1235
+ _$insert(_el$31, () => ` \u251C ${t("priceTier")}: ${v.label}`);
1236
+ _$effect((_$p) => _$setProp(_el$31, "fg", colors().muted, _$p));
1237
+ return _el$31;
1238
+ })());
1239
+ const inner = isLastTier ? " " : "\u2502";
1240
+ const prevV = prevVariants?.find((p) => p.label === v.label) ?? prevVariants?.[ti];
1241
+ 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)]];
1242
+ for (const [fl, fv] of fields) {
1243
+ lines.push((() => {
1244
+ var _el$32 = _$createElement("text");
1245
+ _$insert(_el$32, () => pad13(` ${inner} ${fl}:`) + fv);
1246
+ _$effect((_$p) => _$setProp(_el$32, "fg", colors().muted, _$p));
1247
+ return _el$32;
1248
+ })());
1249
+ }
1250
+ });
1251
+ } else {
1252
+ const v = tiers[0];
1253
+ 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)]];
1254
+ for (const [fl, fv] of fields) {
1255
+ lines.push((() => {
1256
+ var _el$33 = _$createElement("text");
1257
+ _$insert(_el$33, () => pad13(` \u251C ${fl}:`) + fv);
1258
+ _$effect((_$p) => _$setProp(_el$33, "fg", colors().muted, _$p));
1259
+ return _el$33;
1260
+ })());
1261
+ }
1262
+ }
1263
+ const fmtFull = (n) => n > 0 ? n.toLocaleString("en-US") : "\u2014";
1264
+ const limitFields = [[t("priceReq5h"), fmtFull(m.limits.fiveHour)], [t("priceReqWeek"), fmtFull(m.limits.weekly)], [t("priceReqMonth"), fmtFull(m.limits.monthly)]];
1265
+ for (const [fl, fv] of limitFields) {
1266
+ lines.push((() => {
1267
+ var _el$34 = _$createElement("text");
1268
+ _$insert(_el$34, () => pad13(` \u251C ${fl}:`) + fv);
1269
+ _$effect((_$p) => _$setProp(_el$34, "fg", colors().muted, _$p));
1270
+ return _el$34;
1271
+ })());
1272
+ }
1273
+ const meta = [[t("priceSdk"), m.sdk || "-"], [t("priceRetention"), m.retention || "-"], [t("priceTraining"), m.training || "-"]];
1274
+ meta.forEach(([ml, mv], i) => {
1275
+ const conn = i < meta.length - 1 ? "\u251C" : "\u2514";
1276
+ lines.push((() => {
1277
+ var _el$35 = _$createElement("text");
1278
+ _$insert(_el$35, () => pad13(` ${conn} ${ml}:`) + mv);
1279
+ _$effect((_$p) => _$setProp(_el$35, "fg", colors().muted, _$p));
1280
+ return _el$35;
1281
+ })());
1282
+ });
1283
+ return lines;
1157
1284
  }
1158
1285
  const [pal, setPal] = createSignal({
1159
1286
  ...FALLBACK
@@ -1170,7 +1297,10 @@ function PricePanel(props) {
1170
1297
  setPal(p);
1171
1298
  });
1172
1299
  const colors = () => pal();
1173
- const sep = () => "\u2500".repeat(Math.max(1, panelWidth() - 4));
1300
+ const sep = () => {
1301
+ const outer = boxEl && typeof boxEl.width === "number" && boxEl.width > 0 ? boxEl.width : panelWidth();
1302
+ return "\u2500".repeat(Math.max(1, outer - 4));
1303
+ };
1174
1304
  setTimeout(() => {
1175
1305
  const store = loadPricingStore();
1176
1306
  if (store.current.models.length > 0) {
@@ -1181,60 +1311,60 @@ function PricePanel(props) {
1181
1311
  setInterval(() => refreshPricing(), loadConfig().pricingIntervalMs);
1182
1312
  }, 2e3);
1183
1313
  return (() => {
1184
- 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");
1185
- _$insertNode(_el$32, _el$33);
1314
+ 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");
1315
+ _$insertNode(_el$36, _el$37);
1186
1316
  var _ref$2 = boxEl;
1187
- typeof _ref$2 === "function" ? _$use(_ref$2, _el$32) : boxEl = _el$32;
1188
- _$setProp(_el$32, "border", true);
1189
- _$setProp(_el$32, "paddingLeft", 1);
1190
- _$setProp(_el$32, "paddingRight", 1);
1191
- _$setProp(_el$32, "flexDirection", "column");
1192
- _$setProp(_el$32, "gap", 0);
1193
- _$setProp(_el$32, "onSizeChange", () => {
1317
+ typeof _ref$2 === "function" ? _$use(_ref$2, _el$36) : boxEl = _el$36;
1318
+ _$setProp(_el$36, "border", true);
1319
+ _$setProp(_el$36, "paddingLeft", 1);
1320
+ _$setProp(_el$36, "paddingRight", 1);
1321
+ _$setProp(_el$36, "flexDirection", "column");
1322
+ _$setProp(_el$36, "gap", 0);
1323
+ _$setProp(_el$36, "onSizeChange", () => {
1194
1324
  if (resizeTimeout) clearTimeout(resizeTimeout);
1195
1325
  resizeTimeout = setTimeout(() => {
1196
1326
  const w = boxEl ? Math.max(20, boxEl.width ?? 24) : 24;
1197
1327
  setPanelWidth(w);
1198
1328
  }, 100);
1199
1329
  });
1200
- _$insertNode(_el$33, _el$34);
1201
- _$insertNode(_el$33, _el$35);
1202
- _$insertNode(_el$33, _el$40);
1203
- _$setProp(_el$33, "onMouseUp", () => setOpen((o) => !o));
1204
- _$insert(_el$34, () => open() ? "\u25BC " : "\u25B6 ");
1205
- _$insertNode(_el$35, _el$36);
1206
- _$insert(_el$36, () => t("priceTitle"));
1207
- _$insert(_el$33, _$createComponent(Show, {
1330
+ _$insertNode(_el$37, _el$38);
1331
+ _$insertNode(_el$37, _el$39);
1332
+ _$insertNode(_el$37, _el$44);
1333
+ _$setProp(_el$37, "onMouseUp", () => setOpen((o) => !o));
1334
+ _$insert(_el$38, () => open() ? "\u25BC " : "\u25B6 ");
1335
+ _$insertNode(_el$39, _el$40);
1336
+ _$insert(_el$40, () => t("priceTitle"));
1337
+ _$insert(_el$37, _$createComponent(Show, {
1208
1338
  get when() {
1209
1339
  return sharedPricing();
1210
1340
  },
1211
1341
  get children() {
1212
- var _el$37 = _$createElement("span"), _el$38 = _$createTextNode(` (`), _el$39 = _$createTextNode(`)`);
1213
- _$insertNode(_el$37, _el$38);
1214
- _$insertNode(_el$37, _el$39);
1215
- _$insert(_el$37, () => sharedPricing().models.length, _el$39);
1216
- _$effect((_$p) => _$setProp(_el$37, "style", {
1342
+ var _el$41 = _$createElement("span"), _el$42 = _$createTextNode(` (`), _el$43 = _$createTextNode(`)`);
1343
+ _$insertNode(_el$41, _el$42);
1344
+ _$insertNode(_el$41, _el$43);
1345
+ _$insert(_el$41, () => sharedPricing().models.length, _el$43);
1346
+ _$effect((_$p) => _$setProp(_el$41, "style", {
1217
1347
  fg: colors().muted
1218
1348
  }, _$p));
1219
- return _el$37;
1349
+ return _el$41;
1220
1350
  }
1221
- }), _el$40);
1222
- _$insert(_el$40, () => sep().slice(visualWidth((open() ? "\u25BC " : "\u25B6 ") + t("priceTitle") + (sharedPricing() ? ` (${sharedPricing().models.length})` : ""))));
1223
- _$insert(_el$32, _$createComponent(Show, {
1351
+ }), _el$44);
1352
+ _$insert(_el$44, () => sep().slice(visualWidth((open() ? "\u25BC " : "\u25B6 ") + t("priceTitle") + (sharedPricing() ? ` (${sharedPricing().models.length})` : ""))));
1353
+ _$insert(_el$36, _$createComponent(Show, {
1224
1354
  get when() {
1225
1355
  return open();
1226
1356
  },
1227
1357
  get children() {
1228
1358
  return [(() => {
1229
- var _el$41 = _$createElement("text");
1230
- _$insert(_el$41, () => justify(t("priceModelCol"), t("priceReqs")));
1231
- _$effect((_$p) => _$setProp(_el$41, "fg", colors().muted, _$p));
1232
- return _el$41;
1359
+ var _el$45 = _$createElement("text");
1360
+ _$insert(_el$45, () => justify(t("priceModelCol"), t("priceReqs")));
1361
+ _$effect((_$p) => _$setProp(_el$45, "fg", colors().muted, _$p));
1362
+ return _el$45;
1233
1363
  })(), (() => {
1234
- var _el$42 = _$createElement("text");
1235
- _$insert(_el$42, sep);
1236
- _$effect((_$p) => _$setProp(_el$42, "fg", colors().muted, _$p));
1237
- return _el$42;
1364
+ var _el$46 = _$createElement("text");
1365
+ _$insert(_el$46, sep);
1366
+ _$effect((_$p) => _$setProp(_el$46, "fg", colors().muted, _$p));
1367
+ return _el$46;
1238
1368
  })(), _$createComponent(Show, {
1239
1369
  get when() {
1240
1370
  return priceLoading() || !sharedPricing();
@@ -1246,45 +1376,75 @@ function PricePanel(props) {
1246
1376
  },
1247
1377
  get fallback() {
1248
1378
  return (() => {
1249
- var _el$46 = _$createElement("text");
1250
- _$insert(_el$46, () => t("priceLoading"));
1251
- _$effect((_$p) => _$setProp(_el$46, "fg", colors().muted, _$p));
1252
- return _el$46;
1379
+ var _el$53 = _$createElement("text");
1380
+ _$insert(_el$53, () => t("priceLoading"));
1381
+ _$effect((_$p) => _$setProp(_el$53, "fg", colors().muted, _$p));
1382
+ return _el$53;
1253
1383
  })();
1254
1384
  },
1255
1385
  get children() {
1256
1386
  return [_$memo(() => sharedPricing().models.filter((m) => {
1257
1387
  return cfg().focusModels.length === 0 || cfg().focusModels.includes(m.id);
1258
1388
  }).map((m) => renderLimitRow(m))), (() => {
1259
- var _el$44 = _$createElement("text");
1260
- _$insert(_el$44, () => justify(t("priceUpdated"), new Date(sharedPricing().fetchTime).toLocaleTimeString()));
1261
- _$effect((_$p) => _$setProp(_el$44, "fg", colors().muted, _$p));
1262
- return _el$44;
1389
+ var _el$48 = _$createElement("text");
1390
+ _$insert(_el$48, () => justify(t("priceUpdated"), new Date(sharedPricing().fetchTime).toLocaleTimeString()));
1391
+ _$effect((_$p) => _$setProp(_el$48, "fg", colors().muted, _$p));
1392
+ return _el$48;
1263
1393
  })(), _$createComponent(Show, {
1264
1394
  get when() {
1265
1395
  return _$memo(() => !!pricingStore())() && pricingStore().history.length > 0;
1266
1396
  },
1267
1397
  get children() {
1268
- var _el$45 = _$createElement("text");
1269
- _$insert(_el$45, () => t("priceChangesSummary", {
1398
+ var _el$49 = _$createElement("text");
1399
+ _$insert(_el$49, () => t("priceChangesSummary", {
1270
1400
  t: pricingStore().history[0].summary.total,
1271
1401
  a: pricingStore().history[0].summary.added,
1272
1402
  r: pricingStore().history[0].summary.removed,
1273
- p: pricingStore().history[0].summary.priceChanges,
1274
1403
  l: pricingStore().history[0].summary.limitChanges
1275
1404
  }));
1276
- _$effect((_$p) => _$setProp(_el$45, "fg", colors().warning, _$p));
1277
- return _el$45;
1405
+ _$effect((_$p) => _$setProp(_el$49, "fg", colors().warning, _$p));
1406
+ return _el$49;
1407
+ }
1408
+ }), _$createComponent(Show, {
1409
+ get when() {
1410
+ return changedModels().size > 0;
1411
+ },
1412
+ get children() {
1413
+ var _el$50 = _$createElement("text");
1414
+ _$insertNode(_el$50, _$createTextNode(`\u7EFF=\u65B0\u589E \u84DD=\u4EF7\u683C \u6A59=\u9650\u989D\xB7\u70B9\u51FB\u5C55\u5F00`));
1415
+ _$effect((_$p) => _$setProp(_el$50, "fg", colors().muted, _$p));
1416
+ return _el$50;
1417
+ }
1418
+ }), _$createComponent(Show, {
1419
+ get when() {
1420
+ return _$memo(() => !!(pricingStore() && pricingStore().history.length > 0))() && pricingStore().history[0].summary.total > 0;
1421
+ },
1422
+ get children() {
1423
+ return [(() => {
1424
+ var _el$52 = _$createElement("text");
1425
+ _$insert(_el$52, () => `${t("changelogTitle")} (${new Date(pricingStore().history[0].fetchTime).toLocaleTimeString()})`);
1426
+ _$effect((_$p) => _$setProp(_el$52, "fg", colors().muted, _$p));
1427
+ return _el$52;
1428
+ })(), _$memo(() => pricingStore().history[0].changes.slice(0, 12).map((c) => {
1429
+ const label = c.type === "added" ? t("typeAdded") : c.type === "removed" ? t("typeRemoved") : c.type === "pricing" ? t("typePricing") : t("typeLimits");
1430
+ const fg = c.type === "added" ? colors().success : c.type === "removed" ? colors().error : c.type === "pricing" ? colors().primary : colors().warning;
1431
+ return (() => {
1432
+ var _el$54 = _$createElement("text");
1433
+ _$setProp(_el$54, "fg", fg);
1434
+ _$insert(_el$54, () => ` ${label} ${abbreviateName(c.modelName, 20)}`);
1435
+ return _el$54;
1436
+ })();
1437
+ }))];
1278
1438
  }
1279
1439
  })];
1280
1440
  }
1281
1441
  });
1282
1442
  },
1283
1443
  get children() {
1284
- var _el$43 = _$createElement("text");
1285
- _$insert(_el$43, () => t("priceLoading"));
1286
- _$effect((_$p) => _$setProp(_el$43, "fg", colors().muted, _$p));
1287
- return _el$43;
1444
+ var _el$47 = _$createElement("text");
1445
+ _$insert(_el$47, () => t("priceLoading"));
1446
+ _$effect((_$p) => _$setProp(_el$47, "fg", colors().muted, _$p));
1447
+ return _el$47;
1288
1448
  }
1289
1449
  })];
1290
1450
  }
@@ -1297,10 +1457,10 @@ function PricePanel(props) {
1297
1457
  }, _v$12 = {
1298
1458
  fg: colors().muted
1299
1459
  };
1300
- _v$1 !== _p$.e && (_p$.e = _$setProp(_el$32, "borderColor", _v$1, _p$.e));
1301
- _v$10 !== _p$.t && (_p$.t = _$setProp(_el$34, "style", _v$10, _p$.t));
1302
- _v$11 !== _p$.a && (_p$.a = _$setProp(_el$35, "style", _v$11, _p$.a));
1303
- _v$12 !== _p$.o && (_p$.o = _$setProp(_el$40, "style", _v$12, _p$.o));
1460
+ _v$1 !== _p$.e && (_p$.e = _$setProp(_el$36, "borderColor", _v$1, _p$.e));
1461
+ _v$10 !== _p$.t && (_p$.t = _$setProp(_el$38, "style", _v$10, _p$.t));
1462
+ _v$11 !== _p$.a && (_p$.a = _$setProp(_el$39, "style", _v$11, _p$.a));
1463
+ _v$12 !== _p$.o && (_p$.o = _$setProp(_el$44, "style", _v$12, _p$.o));
1304
1464
  return _p$;
1305
1465
  }, {
1306
1466
  e: void 0,
@@ -1308,7 +1468,7 @@ function PricePanel(props) {
1308
1468
  a: void 0,
1309
1469
  o: void 0
1310
1470
  });
1311
- return _el$32;
1471
+ return _el$36;
1312
1472
  })();
1313
1473
  }
1314
1474
  function createSidebarSlot(api) {
@@ -1347,9 +1507,9 @@ function runConfigDialog(api, dialog) {
1347
1507
  return t("wsPromptTitle");
1348
1508
  },
1349
1509
  description: () => (() => {
1350
- var _el$47 = _$createElement("text");
1351
- _$insert(_el$47, () => t("wsPromptDesc"));
1352
- return _el$47;
1510
+ var _el$55 = _$createElement("text");
1511
+ _$insert(_el$55, () => t("wsPromptDesc"));
1512
+ return _el$55;
1353
1513
  })(),
1354
1514
  get placeholder() {
1355
1515
  return t("wsPlaceholder");
@@ -1368,9 +1528,9 @@ function runConfigDialog(api, dialog) {
1368
1528
  return t("cookiePromptTitle");
1369
1529
  },
1370
1530
  description: () => (() => {
1371
- var _el$48 = _$createElement("text");
1372
- _$insert(_el$48, () => t("cookiePromptDesc"));
1373
- return _el$48;
1531
+ var _el$56 = _$createElement("text");
1532
+ _$insert(_el$56, () => t("cookiePromptDesc"));
1533
+ return _el$56;
1374
1534
  })(),
1375
1535
  get placeholder() {
1376
1536
  return t("cookiePlaceholder");
@@ -1518,9 +1678,9 @@ function runSettingsDialog(api, dialog) {
1518
1678
  return t("settingsRefreshUsage");
1519
1679
  },
1520
1680
  description: () => (() => {
1521
- var _el$49 = _$createElement("text");
1522
- _$insertNode(_el$49, _$createTextNode(`\u8F93\u5165\u79D2\u6570\uFF08\u9ED8\u8BA4 60\uFF09`));
1523
- return _el$49;
1681
+ var _el$57 = _$createElement("text");
1682
+ _$insertNode(_el$57, _$createTextNode(`\u8F93\u5165\u79D2\u6570\uFF08\u9ED8\u8BA4 60\uFF09`));
1683
+ return _el$57;
1524
1684
  })(),
1525
1685
  placeholder: "60",
1526
1686
  onConfirm: (val) => {
@@ -1547,9 +1707,9 @@ function runSettingsDialog(api, dialog) {
1547
1707
  return t("settingsRefreshPricing");
1548
1708
  },
1549
1709
  description: () => (() => {
1550
- var _el$51 = _$createElement("text");
1551
- _$insertNode(_el$51, _$createTextNode(`\u8F93\u5165\u79D2\u6570\uFF08\u9ED8\u8BA4 1800\uFF09`));
1552
- return _el$51;
1710
+ var _el$59 = _$createElement("text");
1711
+ _$insertNode(_el$59, _$createTextNode(`\u8F93\u5165\u79D2\u6570\uFF08\u9ED8\u8BA4 1800\uFF09`));
1712
+ return _el$59;
1553
1713
  })(),
1554
1714
  placeholder: "1800",
1555
1715
  onConfirm: (val) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-go-usage-tui",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "OpenCode TUI plugin displaying OpenCode Go usage in the sidebar",
5
5
  "type": "module",
6
6
  "exports": {