@cad0p/pi-usage 0.11.4 → 0.11.5
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/CHANGELOG.md +21 -0
- package/README.md +85 -14
- package/bin/piquota.js +13 -2
- package/extensions/quota-panel.ts +1464 -136
- package/omarchy/cad0p.pi-usage/UsageLogic.js +9 -4
- package/package.json +1 -1
- package/src/cli/args.js +13 -0
- package/src/cli/commands/stats.js +149 -1
- package/src/engine.js +81 -23
- package/src/http.js +34 -1
- package/src/local/history.js +53 -7
- package/src/local/pi-sessions.js +20 -4
- package/src/omarchy/record.js +18 -11
- package/src/providers/opencode-go.js +4 -3
- package/src/render/panel.js +28 -7
package/src/omarchy/record.js
CHANGED
|
@@ -184,17 +184,20 @@ function recordTierLabel(provider) {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
/**
|
|
187
|
-
* Slot label of one account: "
|
|
188
|
-
*
|
|
187
|
+
* Slot label of one account: "" for the base entry (auth.json gives it no
|
|
188
|
+
* number, so no surface may invent one), "#<slot>" for a real sibling, and a
|
|
189
|
+
* named account as-is. A report cached before the fix still says "#1": that is
|
|
190
|
+
* the same base entry and normalizes to "".
|
|
189
191
|
*
|
|
190
192
|
* @param {import("../model.js").QuotaResult} provider
|
|
191
|
-
* @param {number} index
|
|
192
193
|
* @returns {string}
|
|
193
194
|
*/
|
|
194
|
-
function accountLabel(provider
|
|
195
|
-
if (typeof provider.slot === "string"
|
|
196
|
-
|
|
197
|
-
|
|
195
|
+
function accountLabel(provider) {
|
|
196
|
+
if (typeof provider.slot === "string") return provider.slot === "" ? "" : `#${provider.slot}`;
|
|
197
|
+
const account = typeof provider.account === "string" ? provider.account : "";
|
|
198
|
+
if (account === "" || account === "#1") return "";
|
|
199
|
+
if (/^#\d+$/.test(account)) return account;
|
|
200
|
+
return account;
|
|
198
201
|
}
|
|
199
202
|
|
|
200
203
|
/**
|
|
@@ -333,7 +336,11 @@ function compactFailureList(failures) {
|
|
|
333
336
|
labels.push(failures[index].label);
|
|
334
337
|
index += 1;
|
|
335
338
|
}
|
|
336
|
-
|
|
339
|
+
// The unnumbered base entry has no slot label: in prose it is "base", and
|
|
340
|
+
// when it is the only failure the reason alone says everything.
|
|
341
|
+
const named = labels.map((label) => (label === "" ? "base" : label));
|
|
342
|
+
const names = compactLabels(named);
|
|
343
|
+
groups.push(named.length === 1 && named[0] === "base" ? reason : `${names} ${reason}`);
|
|
337
344
|
}
|
|
338
345
|
const text = redact(groups.join(" · "));
|
|
339
346
|
return text.length <= HELP_MAX ? text : `${text.slice(0, HELP_MAX - 1).trimEnd()}…`;
|
|
@@ -370,12 +377,12 @@ function buildFamilyRecord(family, providers, options = {}) {
|
|
|
370
377
|
const accounts = [];
|
|
371
378
|
let okCount = 0;
|
|
372
379
|
|
|
373
|
-
providers.forEach((provider
|
|
374
|
-
const label = accountLabel(provider
|
|
380
|
+
providers.forEach((provider) => {
|
|
381
|
+
const label = accountLabel(provider);
|
|
375
382
|
if (provider.ok) {
|
|
376
383
|
okCount += 1;
|
|
377
384
|
const window = bindingWindow(provider.windows);
|
|
378
|
-
const mapped = window ? mapLimits([window], provider, `${label} · `)[0] : null;
|
|
385
|
+
const mapped = window ? mapLimits([window], provider, label === "" ? "" : `${label} · `)[0] : null;
|
|
379
386
|
if (mapped) limits.push(mapped);
|
|
380
387
|
accounts.push({ id: redact(label), ok: true, status: "", limits: mapLimits(provider.windows, provider) });
|
|
381
388
|
return;
|
|
@@ -41,14 +41,15 @@ function record(value) {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* The account label shown by every surface:
|
|
45
|
-
*
|
|
44
|
+
* The account label shown by every surface: the base auth.json entry has no
|
|
45
|
+
* numeric suffix, so it gets no number; only a real sibling slot is `#<slot>`.
|
|
46
|
+
* The key itself never appears.
|
|
46
47
|
*
|
|
47
48
|
* @param {{ slot?: string | null }} credential
|
|
48
49
|
* @returns {string}
|
|
49
50
|
*/
|
|
50
51
|
function accountLabel(credential) {
|
|
51
|
-
return credential.slot ? `#${credential.slot}` : "
|
|
52
|
+
return credential.slot ? `#${credential.slot}` : "";
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
/**
|
package/src/render/panel.js
CHANGED
|
@@ -161,6 +161,20 @@ function wrapPlain(text, width) {
|
|
|
161
161
|
return lines.length > 0 ? lines : [""];
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
/**
|
|
165
|
+
* The slot label of an account: "" for the base auth.json entry (it has no
|
|
166
|
+
* number, so no surface may invent one), "#<slot>" for a real sibling. A report
|
|
167
|
+
* cached before the fix still says "#1" for the base entry.
|
|
168
|
+
*
|
|
169
|
+
* @param {string | null | undefined} account
|
|
170
|
+
* @returns {string}
|
|
171
|
+
*/
|
|
172
|
+
function slotLabel(account) {
|
|
173
|
+
if (typeof account !== "string") return "";
|
|
174
|
+
if (account === "#1") return "";
|
|
175
|
+
return /^#\d+$/.test(account) ? account : "";
|
|
176
|
+
}
|
|
177
|
+
|
|
164
178
|
/**
|
|
165
179
|
* Per-provider detail lines, without box decoration.
|
|
166
180
|
*
|
|
@@ -176,8 +190,10 @@ export function renderProviderLines(provider, paint, contentWidth = MAX_WIDTH, o
|
|
|
176
190
|
const lines = [];
|
|
177
191
|
|
|
178
192
|
// A multi-account family puts "#<slot>" in the title, so repeating it in the
|
|
179
|
-
// meta line would print the same label twice on one row.
|
|
180
|
-
|
|
193
|
+
// meta line would print the same label twice on one row. The unnumbered base
|
|
194
|
+
// entry contributes nothing, so the meta line does not start with a separator.
|
|
195
|
+
const accountText = provider.account === "#1" ? "" : slotLabel(provider.account) || provider.account || "";
|
|
196
|
+
const meta = options.accountInTitle || accountText === "" ? [] : [accountText];
|
|
181
197
|
if (provider.plan) meta.push(`plan ${provider.plan}`);
|
|
182
198
|
// Claude has two stores, and a broken one is the first thing to rule out when
|
|
183
199
|
// the percentage looks wrong, so the panel names the store it actually read.
|
|
@@ -185,7 +201,11 @@ export function renderProviderLines(provider, paint, contentWidth = MAX_WIDTH, o
|
|
|
185
201
|
if (provider.expiresInMin !== null && provider.expiresInMin <= 120) {
|
|
186
202
|
meta.push(provider.expiresInMin < 0 ? "token EXPIRED" : `token ${provider.expiresInMin}m`);
|
|
187
203
|
}
|
|
188
|
-
lines.push(
|
|
204
|
+
lines.push(
|
|
205
|
+
meta.length === 0
|
|
206
|
+
? clip(paint("bold", title), contentWidth)
|
|
207
|
+
: clip(`${paint("bold", title)} ${paint("dim", `· ${meta.join(" · ")}`)}`, contentWidth),
|
|
208
|
+
);
|
|
189
209
|
|
|
190
210
|
if (!provider.ok) {
|
|
191
211
|
const wrapped = wrapPlain(provider.error ?? "unavailable", contentWidth - 6);
|
|
@@ -318,10 +338,11 @@ export function renderPanel(providers, paint, meta = {}) {
|
|
|
318
338
|
familyCounts.set(provider.family, (familyCounts.get(provider.family) ?? 0) + 1);
|
|
319
339
|
}
|
|
320
340
|
/** @param {import("../model.js").QuotaResult} provider */
|
|
321
|
-
const accountTitle = (provider) =>
|
|
322
|
-
(familyCounts.get(provider.family) ?? 0)
|
|
323
|
-
|
|
324
|
-
|
|
341
|
+
const accountTitle = (provider) => {
|
|
342
|
+
if ((familyCounts.get(provider.family) ?? 0) <= 1) return null;
|
|
343
|
+
const slot = slotLabel(provider.account);
|
|
344
|
+
return slot === "" ? null : `${FAMILY_TITLE[provider.family] ?? provider.label} ${slot}`;
|
|
345
|
+
};
|
|
325
346
|
|
|
326
347
|
// Render once at the hard maximum, then settle on the natural width of the
|
|
327
348
|
// content so long degradation messages cannot stretch every other row.
|