@llblab/pi-codex-usage 0.3.4 โ 0.4.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 +2 -2
- package/CHANGELOG.md +2 -0
- package/README.md +4 -4
- package/banner.png +0 -0
- package/index.ts +47 -32
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -8,6 +8,6 @@
|
|
|
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
|
-
- `Compact dual bar`: Encode the 5-hour and weekly quota windows in the
|
|
11
|
+
- `Compact dual bar`: Encode the 5-hour and weekly quota windows in the ten-character separated-sextant bar.
|
|
12
12
|
- Trigger: Changing statusline formatting.
|
|
13
|
-
- Action: Keep a fixed-width `
|
|
13
|
+
- Action: Keep a fixed-width `xxxxxxxxxx` bar where top sextants represent the 5-hour window and bottom sextants represent the weekly window, with 20 steps per window.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
- `0.4.0` Expanded the dual statusline bar to ten glyphs with 20 steps per quota window, moved its status key near the start of the footer status order, and draws the bar on the themed selected background. Impact: 5-hour and weekly limits now move in 5% increments for 40 total discrete points while empty cells no longer blend into the terminal background.
|
|
4
|
+
- `0.3.5` Refined the compact statusline bar with quadrant glyphs, darker bar coloring, and blink-on-segment-change behavior. Impact: Codex quota changes are easier to notice while routine refreshes stay visually stable.
|
|
3
5
|
- `0.3.4` Added package banner metadata and README hero image. Impact: Pi/package listings can show the Codex Usage banner while npm packages include the image asset.
|
|
4
6
|
- `Fork baseline` Imported `extensions/pi-codex-usage` from `narumiruna/pi-extensions` as a standalone `@llblab/pi-codex-usage` package. Impact: the extension can be installed and maintained independently.
|
|
5
7
|
- `Minimal statusline` Removed command-driven report output and narrowed the extension to a zero-configuration statusline widget. Impact: runtime behavior is automatic while `openai-codex` is active.
|
package/README.md
CHANGED
|
@@ -15,12 +15,12 @@ This repository is a minimal fork of [`narumiruna/pi-extensions/extensions/pi-co
|
|
|
15
15
|
## Features
|
|
16
16
|
|
|
17
17
|
- Shows an empty statusline bar immediately, then refreshes every 30 seconds while the active Pi model uses `openai-codex`
|
|
18
|
-
- Statusline output stays compact, with the `codex` label accented and the
|
|
18
|
+
- Statusline output stays compact, with the `codex` label accented and the quota bar drawn on a themed background
|
|
19
19
|
- Additional returned buckets, including Spark-specific limits, are ignored
|
|
20
20
|
- Pi OpenAI Codex provider auth is used first
|
|
21
21
|
- Codex CLI app-server remains available as a fallback
|
|
22
22
|
- Missing auth, subscription, plan, or quota windows are shown as `n/a`, not as an error
|
|
23
|
-
- Successful updates briefly redraw the bar
|
|
23
|
+
- Successful updates briefly redraw the bar only when a 5% segment changes
|
|
24
24
|
- Network/provider failures keep the last good bar briefly, then show `error`
|
|
25
25
|
- No commands or configuration are required
|
|
26
26
|
|
|
@@ -43,10 +43,10 @@ pi install git:github.com/llblab/pi-codex-usage
|
|
|
43
43
|
Normal usage:
|
|
44
44
|
|
|
45
45
|
```text
|
|
46
|
-
codex
|
|
46
|
+
codex โโโโโโโโโโ
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
The
|
|
49
|
+
The ten-character bar encodes two twenty-step limits at once: 40 total bits of quota state in 10 terminal cells. Each step is 5%: the top quadrants are the 5-hour limit, and the bottom quadrants are the weekly limit.
|
|
50
50
|
|
|
51
51
|
Unavailable because Codex auth or subscription quota is not available:
|
|
52
52
|
|
package/banner.png
CHANGED
|
Binary file
|
package/index.ts
CHANGED
|
@@ -11,26 +11,26 @@ const CODEX_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
|
|
|
11
11
|
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
12
12
|
const REFRESH_INTERVAL_MS = 30 * 1000;
|
|
13
13
|
const REDRAW_BLINK_MS = 150;
|
|
14
|
-
const STATUS_KEY = "codex-usage";
|
|
14
|
+
const STATUS_KEY = "aa-codex-usage";
|
|
15
15
|
const MAX_ERROR_BODY_CHARS = 600;
|
|
16
16
|
const STATUS_LABEL_TEXT = "codex";
|
|
17
17
|
const DUAL_BAR_CHARS = [
|
|
18
18
|
" ",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
19
|
+
"โ",
|
|
20
|
+
"โ",
|
|
21
|
+
"โ",
|
|
22
|
+
"โ",
|
|
23
|
+
"โ",
|
|
24
|
+
"โ",
|
|
25
|
+
"โ",
|
|
26
|
+
"โ",
|
|
27
|
+
"โ",
|
|
28
|
+
"โ",
|
|
29
|
+
"โ",
|
|
30
|
+
"โ",
|
|
31
|
+
"โ",
|
|
32
|
+
"โ",
|
|
33
|
+
"โ",
|
|
34
34
|
];
|
|
35
35
|
|
|
36
36
|
type UsageSource = "pi-auth" | "codex-app-server";
|
|
@@ -222,11 +222,15 @@ export default function codexUsage(pi: ExtensionAPI) {
|
|
|
222
222
|
return;
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
+
const previousReport = cache?.report;
|
|
226
|
+
const blink = previousReport
|
|
227
|
+
? formatReportBar(previousReport) !== formatReportBar(result.report)
|
|
228
|
+
: false;
|
|
225
229
|
failedRefreshes = 0;
|
|
226
230
|
cache = { createdAt: Date.now(), report: result.report };
|
|
227
231
|
setUsageStatusline(ctx, result.report, {
|
|
228
232
|
autoRefresh: true,
|
|
229
|
-
blink
|
|
233
|
+
blink,
|
|
230
234
|
model,
|
|
231
235
|
});
|
|
232
236
|
};
|
|
@@ -684,24 +688,35 @@ export function formatCodexUsageStatusline(
|
|
|
684
688
|
ctx: ExtensionContext,
|
|
685
689
|
_model?: CodexUsageModel,
|
|
686
690
|
): string {
|
|
687
|
-
const
|
|
688
|
-
|
|
691
|
+
const bar = formatReportBar(report);
|
|
692
|
+
return bar ? formatStatuslineBarText(ctx, bar) : formatStatuslineText(ctx, "n/a");
|
|
693
|
+
}
|
|
689
694
|
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
return
|
|
693
|
-
|
|
694
|
-
`[${formatDualLimitBar(snapshot.primary, snapshot.secondary)}]`,
|
|
695
|
-
);
|
|
695
|
+
function formatReportBar(report: CodexUsageReport): string | undefined {
|
|
696
|
+
const snapshot = selectPrimaryCodexSnapshot(report);
|
|
697
|
+
if (!snapshot || (!snapshot.primary && !snapshot.secondary)) return undefined;
|
|
698
|
+
return formatDualLimitBar(snapshot.primary, snapshot.secondary);
|
|
696
699
|
}
|
|
697
700
|
|
|
698
701
|
function formatStatuslineText(ctx: ExtensionContext, value: string): string {
|
|
699
702
|
const label = ctx.ui.theme.fg("accent", STATUS_LABEL_TEXT);
|
|
700
|
-
return `${label} ${ctx.ui.theme.fg("
|
|
703
|
+
return `${label} ${ctx.ui.theme.fg("dim", value)}`;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
function formatStatuslineBarText(ctx: ExtensionContext, bar: string): string {
|
|
707
|
+
const label = ctx.ui.theme.fg("accent", STATUS_LABEL_TEXT);
|
|
708
|
+
const value = ctx.ui.theme.bg(
|
|
709
|
+
"selectedBg",
|
|
710
|
+
ctx.ui.theme.fg("dim", bar),
|
|
711
|
+
);
|
|
712
|
+
return `${label} ${value}`;
|
|
701
713
|
}
|
|
702
714
|
|
|
703
715
|
function formatEmptyStatuslineBar(ctx: ExtensionContext): string {
|
|
704
|
-
return
|
|
716
|
+
return formatStatuslineBarText(
|
|
717
|
+
ctx,
|
|
718
|
+
"\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0",
|
|
719
|
+
);
|
|
705
720
|
}
|
|
706
721
|
|
|
707
722
|
function formatStatuslineProblem(
|
|
@@ -753,10 +768,10 @@ function formatDualLimitBar(
|
|
|
753
768
|
primary: NormalizedRateLimitWindow | undefined,
|
|
754
769
|
secondary: NormalizedRateLimitWindow | undefined,
|
|
755
770
|
): string {
|
|
756
|
-
const primaryParts =
|
|
757
|
-
const secondaryParts =
|
|
771
|
+
const primaryParts = filledTwentieths(primary);
|
|
772
|
+
const secondaryParts = filledTwentieths(secondary);
|
|
758
773
|
let value = "";
|
|
759
|
-
for (let index = 0; index <
|
|
774
|
+
for (let index = 0; index < 10; index++) {
|
|
760
775
|
const leftPart = index * 2 + 1;
|
|
761
776
|
const rightPart = leftPart + 1;
|
|
762
777
|
let mask = 0;
|
|
@@ -769,9 +784,9 @@ function formatDualLimitBar(
|
|
|
769
784
|
return value;
|
|
770
785
|
}
|
|
771
786
|
|
|
772
|
-
function
|
|
787
|
+
function filledTwentieths(window: NormalizedRateLimitWindow | undefined): number {
|
|
773
788
|
if (!window) return 0;
|
|
774
|
-
return Math.round(remainingPercent(window) /
|
|
789
|
+
return Math.round(remainingPercent(window) / 5);
|
|
775
790
|
}
|
|
776
791
|
|
|
777
792
|
function remainingPercent(window: NormalizedRateLimitWindow): number {
|