@llblab/pi-codex-usage 0.8.2 → 0.9.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/AGENTS.md +4 -4
- package/CHANGELOG.md +6 -0
- package/README.md +3 -3
- package/index.ts +42 -11
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
- Trigger: Updating quota polling or error handling.
|
|
9
9
|
- Action: Do not collapse the bar while a request is in flight; only show `n/a` or `error` after repeated failures or no usable quota.
|
|
10
10
|
|
|
11
|
-
- `
|
|
11
|
+
- `Adaptive compact bar`: Encode the server-provided quota windows in the ten-character separated-sextant bar.
|
|
12
12
|
- Trigger: Changing statusline formatting.
|
|
13
|
-
- Action:
|
|
13
|
+
- Action: When both windows exist, keep the classic dual bar with 20 top steps for the 5-hour window and 20 bottom steps for the weekly window. When only one weekly window exists, combine both tiers into one 40-step bar.
|
|
14
14
|
|
|
15
|
-
- `Weekly reset countdown`: Append the weekly reset countdown
|
|
15
|
+
- `Weekly reset countdown`: Append the weekly reset countdown whenever the available weekly window exposes a reset time.
|
|
16
16
|
- Trigger: Changing reset-time normalization or statusline refresh cadence.
|
|
17
|
-
- Action: Keep `d` labels rounded upward in 144-minute day-tenth steps above 24h, show 24h..1h labels in upward-rounded 6-minute hour-tenth steps, keep `m`/`s` labels floored, and hold `0s` until a successful quota refresh reports the next window.
|
|
17
|
+
- Action: Treat the secondary window as weekly in dual-window responses and the sole window as weekly in single-window responses. Keep `d` labels rounded upward in 144-minute day-tenth steps above 24h, show 24h..1h labels in upward-rounded 6-minute hour-tenth steps, keep `m`/`s` labels floored, and hold `0s` until a successful quota refresh reports the next window.
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.9.0: Adaptive Weekly Quota Bar
|
|
6
|
+
|
|
7
|
+
- Added server-driven quota-window display selection. Impact: responses containing both 5-hour and weekly windows keep the classic dual-tier bar, while responses containing only the new weekly window use all 40 bar steps as one unified quota scale instead of leaving one tier empty.
|
|
8
|
+
- Added single-window reset countdown and redraw scheduling. Impact: the weekly reset time remains visible and updates at the correct countdown boundaries regardless of whether OpenAI returns the weekly limit as the primary or secondary window.
|
|
9
|
+
- Extended provisional full-quota stabilization to single-window responses. Impact: transient 0%-used weekly reports remain behind the loading indicator until confirmed, matching the existing dual-window safety behavior.
|
|
10
|
+
|
|
5
11
|
## 0.8.2: Quota Loading Hotfix
|
|
6
12
|
|
|
7
13
|
- Replaced the static empty request placeholder with fixed-width upper and lower markers that move in opposite directions through their respective quota bars, reverse at the ends, and randomly start from either mirrored endpoint phase, using the normal themed bar background. Impact: motion distinguishes startup and model-bucket loading from 100% available quota while preserving the dual-window visual language.
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|

|
|
6
6
|
|
|
7
|
-
This repository is a minimal fork of [`narumiruna/pi-extensions/extensions/pi-codex-usage`](https://github.com/narumiruna/pi-extensions/tree/main/extensions/pi-codex-usage). It keeps the auth and quota-fetching path, but intentionally narrows the interface to the
|
|
7
|
+
This repository is a minimal fork of [`narumiruna/pi-extensions/extensions/pi-codex-usage`](https://github.com/narumiruna/pi-extensions/tree/main/extensions/pi-codex-usage). It keeps the auth and quota-fetching path, but intentionally narrows the interface to the Codex quota windows returned by OpenAI.
|
|
8
8
|
|
|
9
9
|
## Start Here
|
|
10
10
|
|
|
@@ -56,11 +56,11 @@ Spark model usage:
|
|
|
56
56
|
spark ██████████ 7d
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
The ten-character bar
|
|
59
|
+
The ten-character bar adapts to the quota windows returned by OpenAI. When both windows exist, it encodes two twenty-step limits at once: the top quadrants show the 5-hour limit and the bottom quadrants show the weekly limit, with each step representing 5%. When OpenAI returns only the weekly window, both tiers combine into one conventional 40-step bar, with each step representing 2.5%. If any available quota window is exhausted, the bar keeps its shape but switches to the error background color.
|
|
60
60
|
|
|
61
61
|
Before the first usable report for the active quota bucket arrives, two half-height markers move through the same fixed-width themed bar. The upper 5-hour marker travels opposite the lower weekly marker; both reverse smoothly at the ends, and each loader run randomly starts from one of the two mirrored endpoint phases. Their motion distinguishes loading from 100% remaining quota while preserving the normal bar background. A first report claiming both windows are completely unused is treated as provisional for 15 seconds and retried every second, because providers can briefly emit zeroed windows while initializing. Once a usable report exists, refresh requests preserve that last good bar.
|
|
62
62
|
|
|
63
|
-
When the weekly reset time is available, the bar is followed by a countdown. More than a day remains is shown in 144-minute day-tenth steps such as `7d`, `6.9d`, `6.6d`, `5.1d`, `5d`, `3.7d`, `3d`, `2d`, `1.9d`, `1.5d`, and `1.1d`, rounded upward to the next tenth. At 24 hours and below it switches to upward-rounded 6-minute hour-tenth steps such as `24h`, `23.7h`, `20.1h`, `20h`, `19.9h`, `1.4h`, `1.3h`, `1.2h`, `1.1h`, and `1h`. Under an hour it switches to floored minutes, and under a minute to seconds. After the reset timestamp passes, `0s` is held until the next successful quota refresh reports the new weekly window.
|
|
63
|
+
When the weekly reset time is available, including in a single-window response, the bar is followed by a countdown. More than a day remains is shown in 144-minute day-tenth steps such as `7d`, `6.9d`, `6.6d`, `5.1d`, `5d`, `3.7d`, `3d`, `2d`, `1.9d`, `1.5d`, and `1.1d`, rounded upward to the next tenth. At 24 hours and below it switches to upward-rounded 6-minute hour-tenth steps such as `24h`, `23.7h`, `20.1h`, `20h`, `19.9h`, `1.4h`, `1.3h`, `1.2h`, `1.1h`, and `1h`. Under an hour it switches to floored minutes, and under a minute to seconds. After the reset timestamp passes, `0s` is held until the next successful quota refresh reports the new weekly window.
|
|
64
64
|
|
|
65
65
|
When the 5-hour window is exhausted and exposes its own reset time, the statusline adds the 5-hour reset before the weekly reset:
|
|
66
66
|
|
package/index.ts
CHANGED
|
@@ -1098,7 +1098,7 @@ export function formatCodexUsageStatusValue(
|
|
|
1098
1098
|
const capturedNow = typeof modelOrNow === "number" ? modelOrNow : now;
|
|
1099
1099
|
const snapshot = selectActiveUsageSnapshot(report, model);
|
|
1100
1100
|
if (!snapshot || (!snapshot.primary && !snapshot.secondary)) return undefined;
|
|
1101
|
-
const bar =
|
|
1101
|
+
const bar = formatAdaptiveLimitBar(snapshot.primary, snapshot.secondary);
|
|
1102
1102
|
if (isQuotaWindowExhausted(snapshot.primary) && snapshot.primary?.resetAt) {
|
|
1103
1103
|
const primaryCountdown = formatResetCountdown(
|
|
1104
1104
|
snapshot.primary.resetAt,
|
|
@@ -1122,7 +1122,8 @@ export function formatWeeklyResetCountdown(
|
|
|
1122
1122
|
): string | undefined {
|
|
1123
1123
|
const model = typeof modelOrNow === "number" ? undefined : modelOrNow;
|
|
1124
1124
|
const capturedNow = typeof modelOrNow === "number" ? modelOrNow : now;
|
|
1125
|
-
const
|
|
1125
|
+
const snapshot = selectActiveUsageSnapshot(report, model);
|
|
1126
|
+
const resetAt = weeklyWindow(snapshot)?.resetAt;
|
|
1126
1127
|
if (resetAt === undefined) return undefined;
|
|
1127
1128
|
return formatResetCountdown(resetAt, capturedNow);
|
|
1128
1129
|
}
|
|
@@ -1151,9 +1152,9 @@ export function nextResetCountdownDelayMs(
|
|
|
1151
1152
|
model?: CodexUsageModel,
|
|
1152
1153
|
): number | undefined {
|
|
1153
1154
|
const snapshot = selectActiveUsageSnapshot(report, model);
|
|
1154
|
-
const resetTimes = [snapshot?.
|
|
1155
|
-
if (isQuotaWindowExhausted(snapshot
|
|
1156
|
-
resetTimes.push(snapshot
|
|
1155
|
+
const resetTimes = [weeklyWindow(snapshot)?.resetAt];
|
|
1156
|
+
if (snapshot?.secondary && isQuotaWindowExhausted(snapshot.primary)) {
|
|
1157
|
+
resetTimes.push(snapshot.primary?.resetAt);
|
|
1157
1158
|
}
|
|
1158
1159
|
const delays = resetTimes
|
|
1159
1160
|
.filter((resetAt): resetAt is number => resetAt !== undefined)
|
|
@@ -1197,7 +1198,7 @@ function formatReportBar(
|
|
|
1197
1198
|
): string | undefined {
|
|
1198
1199
|
const snapshot = selectActiveUsageSnapshot(report, model);
|
|
1199
1200
|
if (!snapshot || (!snapshot.primary && !snapshot.secondary)) return undefined;
|
|
1200
|
-
return
|
|
1201
|
+
return formatAdaptiveLimitBar(snapshot.primary, snapshot.secondary);
|
|
1201
1202
|
}
|
|
1202
1203
|
|
|
1203
1204
|
function formatStatuslineText(
|
|
@@ -1291,9 +1292,32 @@ function normalizedUsageKey(value: string | undefined): string | undefined {
|
|
|
1291
1292
|
return key || undefined;
|
|
1292
1293
|
}
|
|
1293
1294
|
|
|
1294
|
-
function
|
|
1295
|
+
function formatAdaptiveLimitBar(
|
|
1295
1296
|
primary: NormalizedRateLimitWindow | undefined,
|
|
1296
1297
|
secondary: NormalizedRateLimitWindow | undefined,
|
|
1298
|
+
): string {
|
|
1299
|
+
if (!primary || !secondary) return formatSingleLimitBar(primary ?? secondary);
|
|
1300
|
+
return formatDualLimitBar(primary, secondary);
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
function formatSingleLimitBar(
|
|
1304
|
+
window: NormalizedRateLimitWindow | undefined,
|
|
1305
|
+
): string {
|
|
1306
|
+
const filled = filledParts(window, DUAL_BAR_WIDTH * 4);
|
|
1307
|
+
const partMasks = [1, 4, 2, 8];
|
|
1308
|
+
let value = "";
|
|
1309
|
+
for (let index = 0; index < DUAL_BAR_WIDTH; index++) {
|
|
1310
|
+
const cellParts = Math.min(4, Math.max(0, filled - index * 4));
|
|
1311
|
+
let mask = 0;
|
|
1312
|
+
for (let part = 0; part < cellParts; part++) mask |= partMasks[part] ?? 0;
|
|
1313
|
+
value += DUAL_BAR_CHARS[mask];
|
|
1314
|
+
}
|
|
1315
|
+
return value;
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
function formatDualLimitBar(
|
|
1319
|
+
primary: NormalizedRateLimitWindow,
|
|
1320
|
+
secondary: NormalizedRateLimitWindow,
|
|
1297
1321
|
): string {
|
|
1298
1322
|
const primaryParts = filledTwentieths(primary);
|
|
1299
1323
|
const secondaryParts = filledTwentieths(secondary);
|
|
@@ -1360,14 +1384,21 @@ export function isFullyAvailableReport(
|
|
|
1360
1384
|
model?: CodexUsageModel,
|
|
1361
1385
|
): boolean {
|
|
1362
1386
|
const snapshot = selectActiveUsageSnapshot(report, model);
|
|
1387
|
+
const windows = [snapshot?.primary, snapshot?.secondary].filter(
|
|
1388
|
+
(window): window is NormalizedRateLimitWindow => window !== undefined,
|
|
1389
|
+
);
|
|
1363
1390
|
return (
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
clampPercent(snapshot.primary.usedPercent) === 0 &&
|
|
1367
|
-
clampPercent(snapshot.secondary.usedPercent) === 0
|
|
1391
|
+
windows.length > 0 &&
|
|
1392
|
+
windows.every((window) => clampPercent(window.usedPercent) === 0)
|
|
1368
1393
|
);
|
|
1369
1394
|
}
|
|
1370
1395
|
|
|
1396
|
+
function weeklyWindow(
|
|
1397
|
+
snapshot: NormalizedRateLimitSnapshot | undefined,
|
|
1398
|
+
): NormalizedRateLimitWindow | undefined {
|
|
1399
|
+
return snapshot?.secondary ?? snapshot?.primary;
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1371
1402
|
function selectActiveUsageSnapshot(
|
|
1372
1403
|
report: CodexUsageReport,
|
|
1373
1404
|
model: CodexUsageModel | undefined,
|