Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions lib/codex-manager/formatters/quota-formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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.
*
Expand All @@ -124,10 +142,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 (!reset && label === "quota" && (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;
}

Expand Down Expand Up @@ -163,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);
}

Expand Down Expand Up @@ -198,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));
}
63 changes: 63 additions & 0 deletions test/codex-manager-formatters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,69 @@ describe("compact quota reset timestamps", () => {
);
});

it("hides an unlabeled full quota window with no reset data", () => {
const unlabeledFull = {
status: 200,
planType: "plus",
model: "gpt-5.3-codex",
primary: { usedPercent: 65, windowMinutes: 10080, resetAtMs: SAME_DAY },
secondary: { usedPercent: 0 },
} satisfies 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: 200,
planType: "plus",
model: "gpt-5.3-codex",
primary: { usedPercent: 65, windowMinutes: 10080 },
secondary: { usedPercent: 12 },
} satisfies CodexQuotaSnapshot;
expect(formatCompactQuotaSnapshot(depleted, NOW)).toBe("7d 35% | quota 88%");

const fullWithReset = {
status: 200,
planType: "plus",
model: "gpt-5.3-codex",
primary: { usedPercent: 65, windowMinutes: 10080 },
secondary: { usedPercent: 0, resetAtMs: SAME_DAY },
} satisfies 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("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,
Expand Down