@bacnh85/pi-sub 0.1.1 → 0.1.3
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/README.md +4 -4
- package/index.ts +10 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Pi extension that shows subscription usage for the currently selected supported model provider.
|
|
4
4
|
|
|
5
|
-
V1 supports OpenAI Codex models by reading Pi's auth state from `~/.pi/agent/auth.json` (or `$PI_CODING_AGENT_DIR/auth.json`) and displays a
|
|
5
|
+
V1 supports OpenAI Codex models by reading Pi's auth state from `~/.pi/agent/auth.json` (or `$PI_CODING_AGENT_DIR/auth.json`) and displays a subscription footer status after Pi's built-in status/token usage line only while the active Pi model provider is `openai-codex`.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -26,7 +26,7 @@ pi -e ./extensions/pi-sub
|
|
|
26
26
|
|
|
27
27
|
## What it shows
|
|
28
28
|
|
|
29
|
-
The footer status includes:
|
|
29
|
+
The footer status appears after Pi's built-in status/token usage line and includes:
|
|
30
30
|
|
|
31
31
|
- active account email;
|
|
32
32
|
- subscription plan, such as `Plus`;
|
|
@@ -37,7 +37,7 @@ The footer status includes:
|
|
|
37
37
|
Example subscription line:
|
|
38
38
|
|
|
39
39
|
```text
|
|
40
|
-
Sub Plus user@example.com 5H 85
|
|
40
|
+
Sub · Plus · user@example.com · 5H 85% (18:12) · W 80% (08:00 on 2 Jul) · gpt-5-codex
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
When the current model provider is not supported, `pi-sub` clears its subscription line and does not refresh subscription data.
|
|
@@ -54,7 +54,7 @@ When Pi OpenAI Codex auth is available, `/sub` shows the active account usage:
|
|
|
54
54
|
|
|
55
55
|
```text
|
|
56
56
|
ACCOUNT PLAN 5H USAGE WEEKLY USAGE LAST ACTIVITY
|
|
57
|
-
*
|
|
57
|
+
* user@example.com Plus 85% (18:12) 80% (08:00 on 2 Jul) Now
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
## Refresh behavior
|
package/index.ts
CHANGED
|
@@ -146,7 +146,9 @@ function formatReset(timestampSeconds: number | undefined): string | undefined {
|
|
|
146
146
|
const now = new Date();
|
|
147
147
|
const time = date.toLocaleTimeString(undefined, { hour: "2-digit", minute: "2-digit", hour12: false });
|
|
148
148
|
if (date.toDateString() === now.toDateString()) return time;
|
|
149
|
-
|
|
149
|
+
const day = date.toLocaleDateString(undefined, { day: "numeric" });
|
|
150
|
+
const month = date.toLocaleDateString(undefined, { month: "short" });
|
|
151
|
+
return `${time} on ${day} ${month}`;
|
|
150
152
|
}
|
|
151
153
|
|
|
152
154
|
function usageWindowFromApi(window: UsageApiWindow | undefined): UsageWindow | undefined {
|
|
@@ -260,26 +262,22 @@ function supportedAdapter(model: ModelLike): SubscriptionProviderAdapter | undef
|
|
|
260
262
|
return adapters.find((adapter) => adapter.isModelSupported(model));
|
|
261
263
|
}
|
|
262
264
|
|
|
263
|
-
function formatWindow(window: UsageWindow | undefined,
|
|
265
|
+
function formatWindow(window: UsageWindow | undefined, _compact = true): string {
|
|
264
266
|
if (!window) return "?";
|
|
265
|
-
if (window.percent !== undefined && window.resetLabel) return
|
|
267
|
+
if (window.percent !== undefined && window.resetLabel) return `${window.percent}% (${window.resetLabel})`;
|
|
266
268
|
if (window.label) return window.label;
|
|
267
269
|
if (window.percent !== undefined) return `${window.percent}%`;
|
|
268
270
|
if (window.used !== undefined && window.limit !== undefined) return `${window.used}/${window.limit}`;
|
|
269
271
|
return "?";
|
|
270
272
|
}
|
|
271
273
|
|
|
272
|
-
function compactResetLabel(label: string): string {
|
|
273
|
-
return label.replace(/^0?(\d+:\d+) on (\d+ \w+)$/i, "$2 $1");
|
|
274
|
-
}
|
|
275
|
-
|
|
276
274
|
function maxPercent(account: SubscriptionAccountSnapshot | undefined): number {
|
|
277
275
|
return Math.max(account?.fiveHour?.percent ?? 0, account?.weekly?.percent ?? 0);
|
|
278
276
|
}
|
|
279
277
|
|
|
280
278
|
function renderSubscriptionLine(ctx: ExtensionContext, state: State): void {
|
|
281
279
|
if (!state.adapter) {
|
|
282
|
-
ctx.ui.
|
|
280
|
+
ctx.ui.setStatus(STATUS_KEY, undefined);
|
|
283
281
|
return;
|
|
284
282
|
}
|
|
285
283
|
const theme = ctx.ui.theme;
|
|
@@ -299,11 +297,11 @@ function renderSubscriptionLine(ctx: ExtensionContext, state: State): void {
|
|
|
299
297
|
pieces.push(account?.accountLabel ?? "unknown account");
|
|
300
298
|
pieces.push(`5H ${formatWindow(account?.fiveHour)}`);
|
|
301
299
|
pieces.push(`W ${formatWindow(account?.weekly)}`);
|
|
302
|
-
pieces.push(
|
|
303
|
-
line = pieces.join(" ");
|
|
300
|
+
pieces.push(modelId);
|
|
301
|
+
line = pieces.join(" · ");
|
|
304
302
|
color = maxPercent(account) >= 90 ? "error" : maxPercent(account) >= 80 ? "warning" : "dim";
|
|
305
303
|
}
|
|
306
|
-
ctx.ui.
|
|
304
|
+
ctx.ui.setStatus(STATUS_KEY, theme.fg(color, line));
|
|
307
305
|
}
|
|
308
306
|
|
|
309
307
|
function startTimer(ctx: ExtensionContext, state: State): void {
|
|
@@ -415,7 +413,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
415
413
|
|
|
416
414
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
417
415
|
stopTimer(state);
|
|
418
|
-
ctx.ui.
|
|
416
|
+
ctx.ui.setStatus(STATUS_KEY, undefined);
|
|
419
417
|
});
|
|
420
418
|
|
|
421
419
|
pi.registerCommand("sub", {
|