@khalilgharbaoui/opencode-claude-code-plugin 0.61.2 → 0.62.0

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
@@ -1155,7 +1155,7 @@ function isReadingCurrent(entry, now = Date.now()) {
1155
1155
  function usagePercent(utilization) {
1156
1156
  return Math.round(utilization * 1e3) / 10;
1157
1157
  }
1158
- function createAccountUsageReader(file = accountUsageStorePath) {
1158
+ function createAccountUsageReader(file = accountUsageStorePath, now = Date.now) {
1159
1159
  let identity = "";
1160
1160
  let store = emptyStore();
1161
1161
  const refresh = () => {
@@ -1169,7 +1169,7 @@ function createAccountUsageReader(file = accountUsageStorePath) {
1169
1169
  }
1170
1170
  if (next !== identity) {
1171
1171
  identity = next;
1172
- store = next === "missing" ? emptyStore() : parseStore(path, Date.now());
1172
+ store = next === "missing" ? emptyStore() : parseStore(path, now());
1173
1173
  }
1174
1174
  };
1175
1175
  return {
@@ -1188,8 +1188,10 @@ function createAccountUsageReader(file = accountUsageStorePath) {
1188
1188
  // src/account-sidebar.ts
1189
1189
  var WARNING_PERCENT = 75;
1190
1190
  var NO_READING_TEXT = "no reading yet";
1191
+ var FIVE_HOUR_WINDOW = "five_hour";
1191
1192
  var RESET_WORD = "resets ";
1192
1193
  var SEPARATOR = " \xB7 ";
1194
+ var MAX_DETAIL_INDENT = 12;
1193
1195
  var SHORT_WINDOWS = {
1194
1196
  five_hour: "5h",
1195
1197
  seven_day: "7d",
@@ -1202,6 +1204,9 @@ function shortWindowName(window) {
1202
1204
  if (window === "unknown") return "";
1203
1205
  return SHORT_WINDOWS[window] ?? window.replace(/_/g, " ");
1204
1206
  }
1207
+ function percentLeft(utilization) {
1208
+ return Math.max(0, Math.round(100 - usagePercent(utilization)));
1209
+ }
1205
1210
  var pad = (value) => String(value).padStart(2, "0");
1206
1211
  function sameDay(a, b) {
1207
1212
  return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
@@ -1222,23 +1227,37 @@ function resetSpellings(entry, now) {
1222
1227
  if (entry.resetsText) return [`${RESET_WORD}${entry.resetsText}`, entry.resetsText];
1223
1228
  return [];
1224
1229
  }
1230
+ function stateOf(entry) {
1231
+ if (entry.status === "rejected") return "limited";
1232
+ if (entry.utilization !== null && usagePercent(entry.utilization) >= WARNING_PERCENT) return "warning";
1233
+ return "ok";
1234
+ }
1225
1235
  function rank(entry) {
1226
1236
  if (entry.status === "rejected") return 1e3;
1227
1237
  if (entry.utilization === null) return -1;
1228
1238
  return usagePercent(entry.utilization);
1229
1239
  }
1230
- function pressingWindow(windows, now) {
1240
+ function pressingWindow(windows, now, except) {
1231
1241
  let best;
1232
1242
  for (const [window, entry] of windows) {
1233
- if (!isReadingCurrent(entry, now)) continue;
1243
+ if (window === except || !isReadingCurrent(entry, now)) continue;
1234
1244
  if (!best || rank(entry) > rank(best[1])) best = [window, entry];
1235
1245
  }
1236
1246
  return best;
1237
1247
  }
1248
+ function levelText(window, entry) {
1249
+ const short = shortWindowName(window);
1250
+ const prefix = short ? `${short} ` : "";
1251
+ if (!entry) return `${prefix}100% left`;
1252
+ if (entry.status === "rejected") return `${prefix}limited`;
1253
+ if (entry.utilization === null) return `${prefix}ok`;
1254
+ return `${prefix}${percentLeft(entry.utilization)}% left`;
1255
+ }
1238
1256
  var cells2 = (value) => Array.from(value).length;
1239
1257
  var segmentsCells = (segments) => segments.reduce((sum, segment) => sum + cells2(segment.text), 0);
1240
- function levelRole(state) {
1241
- return state === "limited" ? "error" : state === "warning" ? "effort" : "ok";
1258
+ function levelRole(draft) {
1259
+ if (draft.dimmed) return "muted";
1260
+ return draft.state === "limited" ? "error" : draft.state === "warning" ? "effort" : "ok";
1242
1261
  }
1243
1262
  function fitSegments(segments, budget) {
1244
1263
  const out = [];
@@ -1256,6 +1275,7 @@ function fitSegments(segments, budget) {
1256
1275
  }
1257
1276
  break;
1258
1277
  }
1278
+ while (out.length > 0 && [SEPARATOR, RESET_WORD].includes(out[out.length - 1].text)) out.pop();
1259
1279
  return out;
1260
1280
  }
1261
1281
  function tailSegments(draft, spelling, withTier) {
@@ -1265,10 +1285,8 @@ function tailSegments(draft, spelling, withTier) {
1265
1285
  out2.push({ text: SEPARATOR, role: "muted" }, { text: NO_READING_TEXT, role: "muted" });
1266
1286
  return out2;
1267
1287
  }
1268
- const out = [
1269
- { text: SEPARATOR, role: "muted" },
1270
- { text: draft.level, role: levelRole(draft.state) }
1271
- ];
1288
+ const out = draft.detail ? [] : [{ text: SEPARATOR, role: "muted" }];
1289
+ out.push({ text: draft.level, role: levelRole(draft) });
1272
1290
  const reset = draft.spellings[Math.min(spelling, draft.spellings.length - 1)];
1273
1291
  if (reset) {
1274
1292
  out.push({ text: SEPARATOR, role: "muted" });
@@ -1280,32 +1298,54 @@ function tailSegments(draft, spelling, withTier) {
1280
1298
  }
1281
1299
  return out;
1282
1300
  }
1301
+ function readingDraft(account, name, window, entry, now, detail = false, dimmed = false) {
1302
+ return {
1303
+ account,
1304
+ window,
1305
+ state: entry ? stateOf(entry) : "ok",
1306
+ detail,
1307
+ name,
1308
+ level: levelText(window, entry),
1309
+ dimmed,
1310
+ spellings: entry ? resetSpellings(entry, now) : []
1311
+ };
1312
+ }
1313
+ function accountDrafts(account, windows, known, now, width) {
1314
+ const name = truncate(account, Math.max(1, Math.floor(width / 2)));
1315
+ const fiveHour = windows?.get(FIVE_HOUR_WINDOW);
1316
+ const current = fiveHour && isReadingCurrent(fiveHour, now) ? fiveHour : void 0;
1317
+ const rolled = fiveHour !== void 0 && !current && known.has(account);
1318
+ if (current || rolled) {
1319
+ const other = windows ? pressingWindow(windows, now, FIVE_HOUR_WINDOW) : void 0;
1320
+ const otherState = other ? stateOf(other[1]) : "ok";
1321
+ const drafts = [readingDraft(account, name, FIVE_HOUR_WINDOW, current, now, false, otherState === "limited")];
1322
+ if (other && otherState !== "ok") {
1323
+ const indent = " ".repeat(Math.min(MAX_DETAIL_INDENT, cells2(name) + cells2(SEPARATOR)));
1324
+ drafts.push(readingDraft(account, indent, other[0], other[1], now, true));
1325
+ }
1326
+ return drafts;
1327
+ }
1328
+ const pressing = windows ? pressingWindow(windows, now) : void 0;
1329
+ if (pressing) return [readingDraft(account, name, pressing[0], pressing[1], now)];
1330
+ if (!known.has(account)) return [];
1331
+ return [
1332
+ {
1333
+ account,
1334
+ window: "",
1335
+ state: "none",
1336
+ detail: false,
1337
+ name,
1338
+ level: "",
1339
+ dimmed: false,
1340
+ tier: known.get(account)?.tier,
1341
+ spellings: []
1342
+ }
1343
+ ];
1344
+ }
1283
1345
  function accountUsageLines(usage, now, width = SIDEBAR_ROW_WIDTH, known = /* @__PURE__ */ new Map()) {
1284
1346
  const drafts = [];
1285
1347
  const names = [.../* @__PURE__ */ new Set([...usage.keys(), ...known.keys()])].sort();
1286
- for (const account of names) {
1287
- const name = truncate(account, Math.max(1, Math.floor(width / 2)));
1288
- const windows = usage.get(account);
1289
- const pressing = windows ? pressingWindow(windows, now) : void 0;
1290
- if (!pressing) {
1291
- if (!known.has(account)) continue;
1292
- drafts.push({
1293
- account,
1294
- window: "",
1295
- state: "none",
1296
- name,
1297
- level: "",
1298
- tier: known.get(account)?.tier,
1299
- spellings: []
1300
- });
1301
- continue;
1302
- }
1303
- const [window, entry] = pressing;
1304
- const state = entry.status === "rejected" ? "limited" : entry.utilization !== null && usagePercent(entry.utilization) >= WARNING_PERCENT ? "warning" : "ok";
1305
- const short = shortWindowName(window);
1306
- const level = state === "limited" ? "limited" : entry.utilization === null ? `${short ? `${short} ` : ""}ok` : `${short ? `${short} ` : ""}${Math.round(usagePercent(entry.utilization))}%`;
1307
- drafts.push({ account, window, state, name, level, spellings: resetSpellings(entry, now) });
1308
- }
1348
+ for (const account of names) drafts.push(...accountDrafts(account, usage.get(account), known, now, width));
1309
1349
  const budget = (draft) => Math.max(0, width - cells2(draft.name));
1310
1350
  const spelt = drafts.filter((draft) => draft.state !== "none");
1311
1351
  const last = Math.max(0, ...spelt.map((draft) => draft.spellings.length - 1));
@@ -1320,7 +1360,8 @@ function accountUsageLines(usage, now, width = SIDEBAR_ROW_WIDTH, known = /* @__
1320
1360
  account: draft.account,
1321
1361
  window: draft.window,
1322
1362
  state: draft.state,
1323
- segments: [{ text: draft.name, role: "agent" }, ...fitSegments(tail, budget(draft))]
1363
+ detail: draft.detail,
1364
+ segments: [{ text: draft.name, role: draft.detail ? "muted" : "agent" }, ...fitSegments(tail, budget(draft))]
1324
1365
  };
1325
1366
  });
1326
1367
  }