From 89504d88dade517753b89cdb23922f7c8898f2b5 Mon Sep 17 00:00:00 2001 From: "openai-code-agent[bot]" <242516109+Codex@users.noreply.github.com> Date: Tue, 21 Jul 2026 08:19:58 +0000 Subject: [PATCH] Use relative reset countdowns in footer (hours/days) to match widget behavior Agent-Logs-Url: https://github.com/iurysza/pi-token-tank/sessions/e6d6917a-626b-4221-992c-fdaa61c15946 Co-authored-by: iurysza <4378161+iurysza@users.noreply.github.com> --- README.md | 8 ++++---- src/format.ts | 15 ++++++++++----- tests/format.test.ts | 17 ++++++++++------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 2625305..5b7d008 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Provider-aware subscription quota status for Pi. It follows the active model and fetches that provider’s quota. ```text -▰▱▱▱ 24% ↻ 3:25 +▰▱▱▱ 24% ↻ 3h 25m ``` ## Supported providers @@ -58,19 +58,19 @@ Reload Pi after installation or environment changes. Minimal mode is the default and shows the provider’s primary window: ```text -▰▱▱▱ 24% ↻ 3:25 +▰▱▱▱ 24% ↻ 3h 25m ``` Full mode adds the configured detail windows: ```text -5h ▰▱▱▱ 24% ↻ 3:25 · 7d ▰▱▱▱ 15% ↻ Sun 9:00 +5h ▰▱▱▱ 24% ↻ 3h 25m · 7d ▰▱▱▱ 15% ↻ 4d 11h ``` - Four gauge cells represent 25-point usage buckets. - Percentage colors show urgency: green under 70%, yellow under 90%, red at 90%+. - `~` after a percentage means the extension is showing stale last-good data. -- Reset timestamps use local time. +- Reset countdowns show relative time (`3h 25m`, `4d 11h`, or `soon`). ## Commands diff --git a/src/format.ts b/src/format.ts index a8b6a5d..d64f75e 100644 --- a/src/format.ts +++ b/src/format.ts @@ -45,11 +45,15 @@ export function formatResetTime(resetsAt: number, weekly: boolean): string { return weekly ? `${date.toLocaleDateString("en-US", { weekday: "short" })} ${time}` : time; } -function formatFooterWindow(window: QuotaWindow, label: boolean, stale: boolean, theme: ThemeLike): string { +function formatFooterWindow( + window: QuotaWindow, + label: boolean, + stale: boolean, + theme: ThemeLike, + nowMs: number, +): string { const percent = `${window.usedPercent}%${stale ? "~" : ""}`; - const reset = window.resetsAt - ? ` ↻${label ? " " : " "}${formatResetTime(window.resetsAt, window.resetStyle === "weekday-time")}` - : ""; + const reset = window.resetsAt ? ` ↻ ${formatResetDuration(window.resetsAt - nowMs)}` : ""; const prefix = label ? `${window.shortLabel} ` : ""; return `${theme.fg("dim", `${prefix}${formatGauge(window.usedPercent)} `)}${theme.fg(thresholdColor(window.usedPercent), percent)}${theme.fg("dim", reset)}`; } @@ -59,6 +63,7 @@ export function formatFooter( mode: FooterMode, theme: ThemeLike, windowIds?: readonly string[], + nowMs = Date.now(), ): string { if (quota.state === "missing") return theme.fg("dim", "—"); if (quota.state === "error") return theme.fg("dim", "!"); @@ -71,7 +76,7 @@ export function formatFooter( const stale = quota.state === "stale"; const showLabels = mode === "full" || selected.length === 0; return windows - .map((window) => formatFooterWindow(window, showLabels, stale, theme)) + .map((window) => formatFooterWindow(window, showLabels, stale, theme, nowMs)) .join(theme.fg("dim", " · ")); } diff --git a/tests/format.test.ts b/tests/format.test.ts index 7cfd82a..3827f54 100644 --- a/tests/format.test.ts +++ b/tests/format.test.ts @@ -6,14 +6,17 @@ import type { ProviderQuota, QuotaSnapshot } from "../src/types.js"; const theme = { fg: (color: string, text: string) => `[${color}:${text}]` }; const plainTheme = { fg: (_color: string, text: string) => text }; +const NOW_MS = Date.UTC(2025, 6, 12, 0, 0, 0); +const FIVE_HOUR_RESET_MS = NOW_MS + (3 * 60 + 25) * 60_000; +const WEEKLY_RESET_MS = NOW_MS + ((4 * 24 + 11) * 60) * 60_000; function liveQuota(provider: ProviderQuota["provider"], five: number, weekly: number): ProviderQuota { return { provider, state: "live", fetchedAt: 1752306000000, plan: provider === "codex" ? "plus" : "Allegro", windows: [ - { id: "five-hour", shortLabel: "5h", longLabel: "5h", resetStyle: "time", usedPercent: five, resetsAt: new Date(2025, 6, 12, 3, 25).getTime() }, - { id: "weekly", shortLabel: "7d", longLabel: "Weekly", resetStyle: "weekday-time", usedPercent: weekly, resetsAt: new Date(2025, 6, 13, 9, 0).getTime() }, + { id: "five-hour", shortLabel: "5h", longLabel: "5h", resetStyle: "time", usedPercent: five, resetsAt: FIVE_HOUR_RESET_MS }, + { id: "weekly", shortLabel: "7d", longLabel: "Weekly", resetStyle: "weekday-time", usedPercent: weekly, resetsAt: WEEKLY_RESET_MS }, ], }; } @@ -28,16 +31,16 @@ describe("footer gauges", () => { it("renders exact minimal and full shapes", () => { const quota = liveQuota("codex", 24, 15); - assert.equal(formatFooter(quota, "minimal", plainTheme), "▰▱▱▱ 24% ↻ 3:25"); - assert.equal(formatFooter(quota, "full", plainTheme), "5h ▰▱▱▱ 24% ↻ 3:25 · 7d ▰▱▱▱ 15% ↻ Sun 9:00"); + assert.equal(formatFooter(quota, "minimal", plainTheme, undefined, NOW_MS), "▰▱▱▱ 24% ↻ 3h 25m"); + assert.equal(formatFooter(quota, "full", plainTheme, undefined, NOW_MS), "5h ▰▱▱▱ 24% ↻ 3h 25m · 7d ▰▱▱▱ 15% ↻ 4d 11h"); }); it("falls back to and labels a remaining weekly window", () => { const quota = liveQuota("codex", 24, 34); quota.windows = quota.windows.filter((window) => window.id === "weekly"); assert.equal( - formatFooter(quota, "minimal", plainTheme, ["five-hour"]), - "7d ▰▰▱▱ 34% ↻ Sun 9:00", + formatFooter(quota, "minimal", plainTheme, ["five-hour"], NOW_MS), + "7d ▰▰▱▱ 34% ↻ 4d 11h", ); }); @@ -60,7 +63,7 @@ describe("footer gauges", () => { it("marks cached quota percentages as stale", () => { const quota = liveQuota("kimi", 48, 35); quota.state = "stale"; - assert.equal(formatFooter(quota, "minimal", plainTheme), "▰▰▱▱ 48%~ ↻ 3:25"); + assert.equal(formatFooter(quota, "minimal", plainTheme, undefined, NOW_MS), "▰▰▱▱ 48%~ ↻ 3h 25m"); }); it("colors only exact percentages at thresholds", () => { -- 2.51.2