@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/index.js +64 -5
- package/dist/index.js.map +1 -1
- package/dist/tui.js +75 -34
- package/dist/tui.js.map +1 -1
- package/package.json +1 -1
- package/skills/claude-code-plugin/SKILL.md +11 -7
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,
|
|
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(
|
|
1241
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1363
|
+
detail: draft.detail,
|
|
1364
|
+
segments: [{ text: draft.name, role: draft.detail ? "muted" : "agent" }, ...fitSegments(tail, budget(draft))]
|
|
1324
1365
|
};
|
|
1325
1366
|
});
|
|
1326
1367
|
}
|