@jameslovespancakes/pi-plus 1.0.18 → 1.0.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jameslovespancakes/pi-plus",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
4
4
  "type": "module",
5
5
  "description": "pi and more",
6
6
  "license": "MIT",
@@ -32,6 +32,18 @@ export const OBSERVED_PROVIDERS: ReadonlyArray<readonly [providerId: string, gro
32
32
  export const isFresh = (row: UsageRow, now = Date.now()) => !row.stale && !!row.checkedAt
33
33
  && now - row.checkedAt < CLAUDE_FRESH_MS && (!row.resetAt || row.resetAt > now);
34
34
 
35
+ /**
36
+ * Rows as they stand now. A window whose reset has passed has refilled,
37
+ * whatever it read before, so it reports full with no reset rather than
38
+ * being discarded as unknown until the next poll replaces it. Freshness
39
+ * still comes from `checkedAt`: a failed or old reading stays unknown.
40
+ */
41
+ export function rollOver(rows: UsageRow[], now = Date.now()): UsageRow[] {
42
+ return rows.map((row) => (row.resetAt !== undefined && row.resetAt <= now
43
+ ? { ...row, remaining: 100, resetAt: undefined }
44
+ : row));
45
+ }
46
+
35
47
  /** Percent of combined capacity, not a claim that quota transfers between accounts.
36
48
  * Without published capacities this is explicitly an equal-account estimate.
37
49
  */
@@ -14,7 +14,7 @@ import {
14
14
  } from "../../core/catalog/quality.ts";
15
15
  import { ensureFresh, usageState } from "../../services/usage-service.ts";
16
16
  import { geminiQuotaFamily } from "../../core/gemini/quota.ts";
17
- import { combinedWindow, isGeminiAccount, pooledWindow } from "../../core/quota/pool.ts";
17
+ import { combinedWindow, isGeminiAccount, pooledWindow, rollOver } from "../../core/quota/pool.ts";
18
18
  import { env, isFromProcessEnv, maskSecret, setEnv } from "../../core/env.ts";
19
19
  import { fitId } from "../../ui/format.ts";
20
20
 
@@ -57,7 +57,7 @@ interface Entry {
57
57
 
58
58
  function quotaFor(provider: string, modelId: string): number | undefined {
59
59
  const state = usageState();
60
- const rows = state.rows;
60
+ const rows = rollOver(state.rows);
61
61
  if (provider === "anthropic") {
62
62
  // The pool's figure, not whichever account happens to be listed first.
63
63
  const pool = combinedWindow(rows, "5h", state.accounts, Date.now(), true);
@@ -8,6 +8,7 @@ import {
8
8
  OBSERVED_PROVIDERS,
9
9
  poolAvailability,
10
10
  pooledWindow,
11
+ rollOver,
11
12
  scopedLabels,
12
13
  type UsageRow,
13
14
  } from "../core/quota/pool.ts";
@@ -163,7 +164,9 @@ function renderCell(theme: any, cell: Cell, labelWidth: number, cellWidth: numbe
163
164
  const label = theme.fg(cell.active ? "accent" : "muted", cell.label.slice(0, labelWidth).padEnd(labelWidth));
164
165
  const reset = formatShortReset(cell.resetAt);
165
166
  const resetWidth = 4;
166
- const barWidth = Math.max(4, cellWidth - labelWidth - 6 - resetWidth - 3);
167
+ // label, space, bar, space, 5-wide percent, space, reset: exactly cellWidth,
168
+ // so every row's right column starts under its title.
169
+ const barWidth = Math.max(4, cellWidth - labelWidth - resetWidth - 8);
167
170
 
168
171
  if (cell.remaining === undefined) {
169
172
  return `${label} ${theme.fg("dim", "·".repeat(barWidth))} ${theme.fg("dim", " n/a")}${" ".repeat(resetWidth + 1)}`;
@@ -188,7 +191,8 @@ function renderCell(theme: any, cell: Cell, labelWidth: number, cellWidth: numbe
188
191
  return `${label} ${bar} ${percent} ${theme.fg("dim", reset.padEnd(resetWidth))}`;
189
192
  }
190
193
 
191
- export function renderUsageLines(state: UsageState, theme: any, width: number, active?: ActiveModel): string[] {
194
+ export function renderUsageLines(raw: UsageState, theme: any, width: number, active?: ActiveModel): string[] {
195
+ const state = { ...raw, rows: rollOver(raw.rows) };
192
196
  if (state.loading) return [theme.fg("dim", " usage: loading…")];
193
197
  if (state.rows.length === 0) {
194
198
  if (state.errors.length > 0) return state.errors.map((error) => theme.fg("warning", ` ${error}`));
@@ -219,7 +223,8 @@ export function renderUsageLines(state: UsageState, theme: any, width: number, a
219
223
  return lines.map((line) => truncateToWidth(line, width, ""));
220
224
  }
221
225
 
222
- export function usageSummaryText(state: UsageState): string {
226
+ export function usageSummaryText(raw: UsageState): string {
227
+ const state = { ...raw, rows: rollOver(raw.rows) };
223
228
  const combined = ["5h", "7d", ...scopedLabels(state.rows)].map((label) => {
224
229
  const pool = combinedWindow(state.rows, label, state.accounts, Date.now(), true);
225
230
  return `Claude combined ${label}: ${pool