@monotykamary/pi-better-grok 0.2.0 → 0.2.1

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 CHANGED
@@ -28,7 +28,7 @@ Data comes from the same revision-pinned Grok subscription surface used by the c
28
28
  1. `GET https://cli-chat-proxy.grok.com/v1/user` (identity)
29
29
  2. `GET https://cli-chat-proxy.grok.com/v1/billing?format=credits` (with the `x-userid` header)
30
30
 
31
- Status widget line: `Usage: 66% left · ↺ 5d5h - Mon 5:34 PM` (weekly period + reset clock). Defaults to the widget area below the editor, like pi-better-openai; set `"footer": {"mode": "replace"}` for the full custom footer.
31
+ Status widget line: `Usage: 66% left · ↺ 5d5h - Mon 5:34 PM · 1 banked reset` (weekly period, reset clock, and available banked reset count). Defaults to the widget area below the editor, like pi-better-openai; set `"footer": {"mode": "replace"}` for the full custom footer.
32
32
 
33
33
  ## Banked resets
34
34
 
@@ -53,7 +53,8 @@ JSON config at `~/.pi/agent/extensions/pi-better-grok.json` (global) or `<projec
53
53
  "enabled": true,
54
54
  "refreshIntervalMs": 60000,
55
55
  "showOnlyOnSubscriptionModels": true,
56
- "showResetTimes": true
56
+ "showResetTimes": true,
57
+ "showBankedResets": true
57
58
  },
58
59
  "footer": { "mode": "status" }
59
60
  }
package/index.ts CHANGED
@@ -152,7 +152,12 @@ export default function betterGrok(pi: ExtensionAPI): void {
152
152
  let sessionNameCached = false;
153
153
  let cachedSessionNameLeafId: string | null | undefined;
154
154
  let cachedSessionName: string | undefined;
155
- const usageController = new UsageController(config, updateFooter, fetchUsageSnapshot);
155
+ const usageController = new UsageController(
156
+ config,
157
+ updateFooter,
158
+ fetchUsageSnapshot,
159
+ () => resetController.snapshot?.credits.availableCount ?? null,
160
+ );
156
161
  const resetController = new ResetController();
157
162
  let multiproviderService: MultiproviderService | undefined;
158
163
  let unsubscribeMultiprovider: (() => void) | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monotykamary/pi-better-grok",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Improve Grok/xAI in pi with fast mode, subscription usage stats, banked reset redemption, multiprovider pools, footer polish, and settings — mirroring pi-better-openai.",
5
5
  "keywords": [
6
6
  "footer",
package/src/config.ts CHANGED
@@ -25,6 +25,7 @@ export type UsageConfig = {
25
25
  refreshIntervalMs?: number;
26
26
  showOnlyOnSubscriptionModels?: boolean;
27
27
  showResetTimes?: boolean;
28
+ showBankedResets?: boolean;
28
29
  };
29
30
  export type FooterConfig = { mode?: FooterMode };
30
31
 
@@ -64,6 +65,7 @@ export const DEFAULT_USAGE_CONFIG: Required<UsageConfig> = {
64
65
  refreshIntervalMs: 60_000,
65
66
  showOnlyOnSubscriptionModels: true,
66
67
  showResetTimes: true,
68
+ showBankedResets: true,
67
69
  };
68
70
  export const DEFAULT_FOOTER_CONFIG: Required<FooterConfig> = { mode: "status" };
69
71
  export const DEFAULT_CONFIG: ConfigFile = {
@@ -193,6 +195,16 @@ export const USAGE_SETTING_DESCRIPTORS: SettingsOptionDescriptor[] = [
193
195
  parse: (rawValue) => rawValue === "true",
194
196
  current: (config) => String(config.usage.showResetTimes),
195
197
  },
198
+ {
199
+ id: "usage.showBankedResets",
200
+ section: "usage",
201
+ key: "showBankedResets",
202
+ label: "Banked reset count",
203
+ description: "Show the available banked SuperGrok reset count in the usage status line.",
204
+ values: ["true", "false"],
205
+ parse: (rawValue) => rawValue === "true",
206
+ current: (config) => String(config.usage.showBankedResets),
207
+ },
196
208
  ];
197
209
 
198
210
  export const FAST_SETTING_DESCRIPTORS: SettingsOptionDescriptor[] = [
@@ -59,15 +59,18 @@ export class UsageController {
59
59
  private readonly getConfig: (ctx: ExtensionContext) => ResolvedConfig;
60
60
  private readonly updateFooter: (ctx: ExtensionContext) => void;
61
61
  private readonly fetchSnapshot: FetchUsageSnapshot;
62
+ private readonly getBankedResets: (() => number | null) | undefined;
62
63
 
63
64
  constructor(
64
65
  getConfig: (ctx: ExtensionContext) => ResolvedConfig,
65
66
  updateFooter: (ctx: ExtensionContext) => void,
66
67
  fetchSnapshot: FetchUsageSnapshot,
68
+ getBankedResets?: () => number | null,
67
69
  ) {
68
70
  this.getConfig = getConfig;
69
71
  this.updateFooter = updateFooter;
70
72
  this.fetchSnapshot = fetchSnapshot;
73
+ this.getBankedResets = getBankedResets;
71
74
  }
72
75
 
73
76
  get snapshot(): UsageSnapshot | undefined {
@@ -83,7 +86,10 @@ export class UsageController {
83
86
  !this.usageError &&
84
87
  cfg.usage.enabled &&
85
88
  isGrokSubscriptionModel(ctx, cfg, isUsingOAuth)
86
- ? formatUsageSnapshot(this.usageSnapshot, cfg.usage)
89
+ ? formatUsageSnapshot(this.usageSnapshot, {
90
+ ...cfg.usage,
91
+ bankedResets: this.getBankedResets?.() ?? null,
92
+ })
87
93
  : undefined;
88
94
  }
89
95
 
@@ -99,7 +105,10 @@ export class UsageController {
99
105
  this.usageUpdatedAt && Date.now() - this.usageUpdatedAt > cfg.usage.refreshIntervalMs * 2
100
106
  ? ` · stale`
101
107
  : "";
102
- return `${formatUsageSnapshot(this.usageSnapshot, cfg.usage)}${stale}`;
108
+ return `${formatUsageSnapshot(this.usageSnapshot, {
109
+ ...cfg.usage,
110
+ bankedResets: this.getBankedResets?.() ?? null,
111
+ })}${stale}`;
103
112
  }
104
113
 
105
114
  formatDetail(ctx: ExtensionContext): string {
package/src/usage.ts CHANGED
@@ -230,9 +230,20 @@ export function formatCents(cents: number | null): string {
230
230
  return typeof cents === "number" ? `$${(cents / 100).toFixed(2)}` : "--";
231
231
  }
232
232
 
233
+ export type UsageStatusOptions = {
234
+ showResetTimes: boolean;
235
+ showBankedResets?: boolean;
236
+ bankedResets?: number | null;
237
+ };
238
+
239
+ export function formatBankedResetsSuffix(count: number | null | undefined): string | null {
240
+ if (typeof count !== "number" || !Number.isInteger(count) || count <= 0) return null;
241
+ return `${count} banked reset${count === 1 ? "" : "s"}`;
242
+ }
243
+
233
244
  export function formatUsageSnapshot(
234
245
  snapshot: UsageSnapshot,
235
- options: { showResetTimes: boolean },
246
+ options: UsageStatusOptions,
236
247
  now = Date.now(),
237
248
  ): string {
238
249
  const used = snapshot.creditUsagePercent;
@@ -244,6 +255,9 @@ export function formatUsageSnapshot(
244
255
  const clock = formatResetClock(seconds, now);
245
256
  if (countdown && clock) parts.push(`↺ ${countdown} - ${clock}`);
246
257
  }
258
+ const banked =
259
+ options.showBankedResets === false ? null : formatBankedResetsSuffix(options.bankedResets);
260
+ if (banked) parts.push(banked);
247
261
  return parts.join(" · ");
248
262
  }
249
263