rinco-pi-hud 1.1.1 → 1.2.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/docs/footer.md
CHANGED
|
@@ -149,7 +149,7 @@ $separator → $sep
|
|
|
149
149
|
|
|
150
150
|
The status line automatically switches quota display based on model provider:
|
|
151
151
|
|
|
152
|
-
- **openai-codex**: Uses Pi Model Registry's Codex Auth to query ChatGPT usage endpoint; falls back to `codex app-server --listen stdio://`. Shows weekly limit percentage, e.g. `codex 75% wk
|
|
152
|
+
- **openai-codex**: Uses Pi Model Registry's Codex Auth to query ChatGPT usage endpoint; falls back to `codex app-server --listen stdio://`. Shows the remaining 5h window with its reset time plus the weekly limit percentage, e.g. `codex 60% 5h (14:30) 75% wk` (the reset stamp becomes `14:30 12 Feb` when the window rolls over on a later day).
|
|
153
153
|
- **token-switch**: Uses `TOKEN_SWITCH_API_KEY` environment variable to query billing subscription and usage. Shows available balance, e.g. `token-switch $750.00`.
|
|
154
154
|
|
|
155
155
|
Both queries use 15-second timeout, 5-minute cache, and auto-refresh. Switching models via `/model` forces a refresh.
|
|
@@ -54,31 +54,48 @@ export function formatCodexUsageStatusline(
|
|
|
54
54
|
const snapshot = selectSnapshotForModel(report, model);
|
|
55
55
|
if (!snapshot) return "usage unavailable";
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
if (weekly) return formatStatuslineWindow(snapshot, weekly);
|
|
59
|
-
|
|
60
|
-
// A model-specific bucket may omit the long window; fall back to the account-wide one.
|
|
57
|
+
// A model-specific bucket may omit a window; fall back to the account-wide one.
|
|
61
58
|
const codexSnapshot = report.snapshots.find(isPrimaryCodexSnapshot);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
const fallbackSnapshot = codexSnapshot !== snapshot ? codexSnapshot : undefined;
|
|
60
|
+
const short = selectShortWindow(snapshot) ?? selectShortWindow(fallbackSnapshot);
|
|
61
|
+
const weekly = selectWeeklyWindow(snapshot) ?? selectWeeklyWindow(fallbackSnapshot);
|
|
62
|
+
|
|
63
|
+
const ownsWindow = Boolean(selectShortWindow(snapshot) ?? selectWeeklyWindow(snapshot));
|
|
64
|
+
const labelSnapshot = ownsWindow ? snapshot : (fallbackSnapshot ?? snapshot);
|
|
65
|
+
const parts = [formatStatuslinePrefix(labelSnapshot)];
|
|
66
|
+
|
|
67
|
+
if (short) parts.push(formatStatuslineWindow(short, "5h", true));
|
|
68
|
+
if (weekly) parts.push(formatStatuslineWindow(weekly, "weekly", false));
|
|
69
|
+
if (!short && !weekly) parts.push("limits unavailable");
|
|
66
70
|
|
|
67
|
-
return
|
|
71
|
+
return parts.join(" ");
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
function formatStatuslineWindow(
|
|
71
|
-
snapshot: NormalizedRateLimitSnapshot,
|
|
72
75
|
window: NormalizedRateLimitWindow,
|
|
76
|
+
fallback: "5h" | "weekly",
|
|
77
|
+
withReset: boolean,
|
|
73
78
|
): string {
|
|
74
|
-
|
|
79
|
+
const label = formatWindowLabel(window, fallback, true);
|
|
80
|
+
const reset = withReset && window.resetsAt ? ` (${formatCompactReset(window.resetsAt)})` : "";
|
|
81
|
+
return `${formatRemainingPercent(window)} ${label}${reset}`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// The short (rolling) window is the one shorter than a day; accounts that only
|
|
85
|
+
// report a single long window have no short window at all.
|
|
86
|
+
function selectShortWindow(
|
|
87
|
+
snapshot: NormalizedRateLimitSnapshot | undefined,
|
|
88
|
+
): NormalizedRateLimitWindow | undefined {
|
|
89
|
+
if (!snapshot?.primary) return undefined;
|
|
90
|
+
return isLongWindow(snapshot.primary) ? undefined : snapshot.primary;
|
|
75
91
|
}
|
|
76
92
|
|
|
77
93
|
// Prefer the secondary (long) window, but some accounts only report a single
|
|
78
94
|
// long window as `primary` — treat any window of a day or more as the weekly one.
|
|
79
95
|
function selectWeeklyWindow(
|
|
80
|
-
snapshot: NormalizedRateLimitSnapshot,
|
|
96
|
+
snapshot: NormalizedRateLimitSnapshot | undefined,
|
|
81
97
|
): NormalizedRateLimitWindow | undefined {
|
|
98
|
+
if (!snapshot) return undefined;
|
|
82
99
|
if (snapshot.secondary) return snapshot.secondary;
|
|
83
100
|
if (snapshot.primary && isLongWindow(snapshot.primary)) return snapshot.primary;
|
|
84
101
|
return undefined;
|
|
@@ -256,6 +273,20 @@ function formatReset(epochSeconds: number): string {
|
|
|
256
273
|
return `${time} on ${day} ${month}`;
|
|
257
274
|
}
|
|
258
275
|
|
|
276
|
+
// Compact reset stamp for the footer usage row: `14:30`, or `14:30 12 Feb`
|
|
277
|
+
// when the window rolls over on a later day.
|
|
278
|
+
function formatCompactReset(epochSeconds: number): string {
|
|
279
|
+
const reset = new Date(epochSeconds * 1000);
|
|
280
|
+
if (Number.isNaN(reset.getTime())) return "unknown";
|
|
281
|
+
|
|
282
|
+
const time = `${reset.getHours().toString().padStart(2, "0")}:${reset
|
|
283
|
+
.getMinutes()
|
|
284
|
+
.toString()
|
|
285
|
+
.padStart(2, "0")}`;
|
|
286
|
+
if (reset.toDateString() === new Date().toDateString()) return time;
|
|
287
|
+
return `${time} ${reset.getDate()} ${reset.toLocaleDateString(undefined, { month: "short" })}`;
|
|
288
|
+
}
|
|
289
|
+
|
|
259
290
|
export function formatQueryErrors(errors: UsageQueryError[]): string {
|
|
260
291
|
const lines = ["Unable to read Codex usage."];
|
|
261
292
|
for (const error of errors) {
|