From 7c9daac8179d100f2d9d4e6c1618ae50e1ae3823 Mon Sep 17 00:00:00 2001 From: choa Date: Sat, 8 Aug 2026 08:36:31 +0900 Subject: [PATCH 1/3] fix(quota-display): hide unlabeled full quota window with no reset data Since the 2026-07/08 upstream limit changes the short window is reported with no duration and no reset timestamp, so every account renders a permanent "quota 100%" segment in check/list/menu summaries. Hide exactly that uninformative shape (unlabeled + full + no reset); the segment reappears as soon as the window reports a duration, any depletion, or a reset time. Covered by two new formatter tests. --- .../formatters/quota-formatters.ts | 13 ++++- test/codex-manager-formatters.test.ts | 53 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/lib/codex-manager/formatters/quota-formatters.ts b/lib/codex-manager/formatters/quota-formatters.ts index 1700815a..cd9da84a 100644 --- a/lib/codex-manager/formatters/quota-formatters.ts +++ b/lib/codex-manager/formatters/quota-formatters.ts @@ -124,10 +124,21 @@ function formatCompactQuotaPart( return null; } const left = quotaLeftPercentFromUsed(usedPercent); + // The reset validity is computed regardless of showReset: it also feeds the + // uninformative-window check below, so hiding stays consistent across the + // compact (no-reset) and check (with-reset) surfaces. + const reset = formatQuotaResetAt(resetAtMs, now); + // An unlabeled window ("quota" — upstream reported no duration) that sits at + // 100% left with no reset timestamp carries no actionable signal; since the + // 2026-07/08 upstream limit changes it renders as a permanent "quota 100%" + // on every account. Hide exactly that shape: the segment reappears as soon + // as the window reports a duration, any depletion, or a reset time. + if (label === "quota" && !reset && (left === undefined || left >= 100)) { + return null; + } const part = `${label} ${left}%`; if (!options.showReset) return part; // A missing or malformed reset timestamp must never drop the percentage. - const reset = formatQuotaResetAt(resetAtMs, now); return reset ? `${part}, resets ${reset}` : part; } diff --git a/test/codex-manager-formatters.test.ts b/test/codex-manager-formatters.test.ts index 55fd2eb2..5d2d27bc 100644 --- a/test/codex-manager-formatters.test.ts +++ b/test/codex-manager-formatters.test.ts @@ -250,6 +250,59 @@ describe("compact quota reset timestamps", () => { ); }); + it("hides an unlabeled full quota window with no reset data", () => { + const unlabeledFull = { + status: "ok", + planType: "plus", + model: "gpt-5.3-codex", + primary: { usedPercent: 65, windowMinutes: 10080, resetAtMs: SAME_DAY }, + secondary: { + usedPercent: 0, + windowMinutes: undefined, + resetAtMs: undefined, + }, + } as unknown as CodexQuotaSnapshot; + expect( + formatCompactQuotaSnapshot(unlabeledFull, NOW, { showReset: true }), + ).toBe(`7d 35%, resets ${formatQuotaResetAt(SAME_DAY, NOW)}`); + expect(formatCompactQuotaSnapshot(unlabeledFull, NOW)).toBe("7d 35%"); + }); + + it("keeps an unlabeled window once it reports depletion or a reset", () => { + const depleted = { + status: "ok", + planType: "plus", + model: "gpt-5.3-codex", + primary: { usedPercent: 65, windowMinutes: 10080, resetAtMs: undefined }, + secondary: { + usedPercent: 12, + windowMinutes: undefined, + resetAtMs: undefined, + }, + } as unknown as CodexQuotaSnapshot; + expect(formatCompactQuotaSnapshot(depleted, NOW)).toBe("7d 35% | quota 88%"); + + const fullWithReset = { + status: "ok", + planType: "plus", + model: "gpt-5.3-codex", + primary: { usedPercent: 65, windowMinutes: 10080, resetAtMs: undefined }, + secondary: { + usedPercent: 0, + windowMinutes: undefined, + resetAtMs: SAME_DAY, + }, + } as unknown as CodexQuotaSnapshot; + expect(formatCompactQuotaSnapshot(fullWithReset, NOW)).toBe( + "7d 35% | quota 100%", + ); + expect( + formatCompactQuotaSnapshot(fullWithReset, NOW, { showReset: true }), + ).toBe( + `7d 35% | quota 100%, resets ${formatQuotaResetAt(SAME_DAY, NOW)}`, + ); + }); + it("formatQuotaSnapshotForDashboard is the check line and shows resets", () => { const display = { showQuotaDetails: true, From db3ffeb6dc7bafa0d40d55a6752a7f0e188a0766 Mon Sep 17 00:00:00 2001 From: choa Date: Sat, 8 Aug 2026 15:49:30 +0900 Subject: [PATCH 2/3] =?UTF-8?q?test(quota-display):=20address=20review=20?= =?UTF-8?q?=E2=80=94=20numeric=20status=20and=20satisfies-typed=20fixtures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeRabbit review: the new fixtures used status: "ok" masked by an as-unknown cast while CodexQuotaSnapshot declares status: number. Switch to status: 200 and replace the casts with satisfies so the compiler checks the fixtures; omit optional window fields instead of passing explicit undefined. --- test/codex-manager-formatters.test.ts | 34 +++++++++------------------ 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/test/codex-manager-formatters.test.ts b/test/codex-manager-formatters.test.ts index 5d2d27bc..a05abdb3 100644 --- a/test/codex-manager-formatters.test.ts +++ b/test/codex-manager-formatters.test.ts @@ -252,16 +252,12 @@ describe("compact quota reset timestamps", () => { it("hides an unlabeled full quota window with no reset data", () => { const unlabeledFull = { - status: "ok", + status: 200, planType: "plus", model: "gpt-5.3-codex", primary: { usedPercent: 65, windowMinutes: 10080, resetAtMs: SAME_DAY }, - secondary: { - usedPercent: 0, - windowMinutes: undefined, - resetAtMs: undefined, - }, - } as unknown as CodexQuotaSnapshot; + secondary: { usedPercent: 0 }, + } satisfies CodexQuotaSnapshot; expect( formatCompactQuotaSnapshot(unlabeledFull, NOW, { showReset: true }), ).toBe(`7d 35%, resets ${formatQuotaResetAt(SAME_DAY, NOW)}`); @@ -270,29 +266,21 @@ describe("compact quota reset timestamps", () => { it("keeps an unlabeled window once it reports depletion or a reset", () => { const depleted = { - status: "ok", + status: 200, planType: "plus", model: "gpt-5.3-codex", - primary: { usedPercent: 65, windowMinutes: 10080, resetAtMs: undefined }, - secondary: { - usedPercent: 12, - windowMinutes: undefined, - resetAtMs: undefined, - }, - } as unknown as CodexQuotaSnapshot; + primary: { usedPercent: 65, windowMinutes: 10080 }, + secondary: { usedPercent: 12 }, + } satisfies CodexQuotaSnapshot; expect(formatCompactQuotaSnapshot(depleted, NOW)).toBe("7d 35% | quota 88%"); const fullWithReset = { - status: "ok", + status: 200, planType: "plus", model: "gpt-5.3-codex", - primary: { usedPercent: 65, windowMinutes: 10080, resetAtMs: undefined }, - secondary: { - usedPercent: 0, - windowMinutes: undefined, - resetAtMs: SAME_DAY, - }, - } as unknown as CodexQuotaSnapshot; + primary: { usedPercent: 65, windowMinutes: 10080 }, + secondary: { usedPercent: 0, resetAtMs: SAME_DAY }, + } satisfies CodexQuotaSnapshot; expect(formatCompactQuotaSnapshot(fullWithReset, NOW)).toBe( "7d 35% | quota 100%", ); From 8a96b8b191dbaefa4cd9c2c64d49ee4c6abbef7c Mon Sep 17 00:00:00 2001 From: ndycode Date: Sun, 9 Aug 2026 02:02:57 +0800 Subject: [PATCH 3/3] fix(quota-display): cover all-hidden fallback --- .../formatters/quota-formatters.ts | 54 ++++++++++++++++++- test/codex-manager-formatters.test.ts | 22 ++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/lib/codex-manager/formatters/quota-formatters.ts b/lib/codex-manager/formatters/quota-formatters.ts index cd9da84a..210e15fc 100644 --- a/lib/codex-manager/formatters/quota-formatters.ts +++ b/lib/codex-manager/formatters/quota-formatters.ts @@ -67,7 +67,8 @@ export function formatQuotaSnapshotForDashboard( now = Date.now(), ): string { if (!settings.showQuotaDetails) return "live session OK"; - return `live session OK (${formatCompactQuotaSnapshot(snapshot, now, { showReset: true })})`; + const summary = formatCompactQuotaSnapshot(snapshot, now, { showReset: true }); + return summary ? `live session OK (${summary})` : "live session OK"; } export function quotaCacheEntryToSnapshot( @@ -101,6 +102,23 @@ function formatCompactQuotaWindowLabel( return `${windowMinutes}m`; } +function isUninformativeFullQuotaWindow( + windowMinutes: number | undefined, + usedPercent: number | undefined, + resetAtMs: number | undefined, + now: number, +): boolean { + if (formatCompactQuotaWindowLabel(windowMinutes) !== "quota") return false; + if (typeof usedPercent !== "number" || !Number.isFinite(usedPercent)) { + return false; + } + const left = quotaLeftPercentFromUsed(usedPercent); + return ( + !formatQuotaResetAt(resetAtMs, now) && + (left === undefined || left >= 100) + ); +} + /** * Options shared by the compact quota formatters. * @@ -133,7 +151,7 @@ function formatCompactQuotaPart( // 2026-07/08 upstream limit changes it renders as a permanent "quota 100%" // on every account. Hide exactly that shape: the segment reappears as soon // as the window reports a duration, any depletion, or a reset time. - if (label === "quota" && !reset && (left === undefined || left >= 100)) { + if (!reset && label === "quota" && (left === undefined || left >= 100)) { return null; } const part = `${label} ${left}%`; @@ -174,6 +192,22 @@ export function formatCompactQuotaSnapshot( if (parts.length > 0) { return parts.join(" | "); } + if ( + isUninformativeFullQuotaWindow( + snapshot.primary.windowMinutes, + snapshot.primary.usedPercent, + snapshot.primary.resetAtMs, + now, + ) || + isUninformativeFullQuotaWindow( + snapshot.secondary.windowMinutes, + snapshot.secondary.usedPercent, + snapshot.secondary.resetAtMs, + now, + ) + ) { + return ""; + } return formatQuotaSnapshotLine(snapshot); } @@ -209,5 +243,21 @@ export function formatAccountQuotaSummary( if (parts.length > 0) { return parts.join(" | "); } + if ( + isUninformativeFullQuotaWindow( + entry.primary.windowMinutes, + entry.primary.usedPercent, + entry.primary.resetAtMs, + now, + ) || + isUninformativeFullQuotaWindow( + entry.secondary.windowMinutes, + entry.secondary.usedPercent, + entry.secondary.resetAtMs, + now, + ) + ) { + return ""; + } return formatQuotaSnapshotLine(quotaCacheEntryToSnapshot(entry)); } diff --git a/test/codex-manager-formatters.test.ts b/test/codex-manager-formatters.test.ts index a05abdb3..16203ff3 100644 --- a/test/codex-manager-formatters.test.ts +++ b/test/codex-manager-formatters.test.ts @@ -291,6 +291,28 @@ describe("compact quota reset timestamps", () => { ); }); + it("does not restore quota text when both windows are uninformative", () => { + const allHidden = { + status: 200, + planType: "plus", + model: "gpt-5.3-codex", + primary: { usedPercent: 0 }, + secondary: { usedPercent: 0 }, + } satisfies CodexQuotaSnapshot; + + expect(formatCompactQuotaSnapshot(allHidden, NOW)).toBe(""); + expect( + formatCompactQuotaSnapshot(allHidden, NOW, { showReset: true }), + ).toBe(""); + expect( + formatQuotaSnapshotForDashboard( + allHidden, + { showQuotaDetails: true } as DashboardDisplaySettings, + NOW, + ), + ).toBe("live session OK"); + }); + it("formatQuotaSnapshotForDashboard is the check line and shows resets", () => { const display = { showQuotaDetails: true,