diff --git a/extensions/codex/src/app-server/rate-limits.test.ts b/extensions/codex/src/app-server/rate-limits.test.ts index 5029ba8c042..8a26a1972ec 100644 --- a/extensions/codex/src/app-server/rate-limits.test.ts +++ b/extensions/codex/src/app-server/rate-limits.test.ts @@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest"; import { formatCodexUsageLimitErrorMessage, resolveCodexUsageLimitResetAtMs, + summarizeCodexRateLimits, summarizeCodexAccountUsage, } from "./rate-limits.js"; @@ -66,3 +67,32 @@ describe("Codex rate limit blocking resets", () => { expect(summarizeCodexAccountUsage(payload, nowMs)?.blockedUntilMs).toBe(weeklyReset * 1000); }); }); + +describe("summarizeCodexRateLimits", () => { + it("formats status limits like provider usage summaries", () => { + const nowMs = 1_700_000_000_000; + const nowSeconds = nowMs / 1000; + + expect( + summarizeCodexRateLimits( + { + rateLimits: { + limitId: "codex", + limitName: "Codex", + primary: { + usedPercent: 26, + windowDurationMins: 300, + resetsAt: nowSeconds + 3 * 60 * 60, + }, + secondary: { + usedPercent: 4, + windowDurationMins: 7 * 24 * 60, + resetsAt: nowSeconds + 7 * 24 * 60 * 60, + }, + }, + }, + nowMs, + ), + ).toBe("Codex: primary 74% left ⏱3h · secondary 96% left ⏱7d"); + }); +}); diff --git a/extensions/codex/src/app-server/rate-limits.ts b/extensions/codex/src/app-server/rate-limits.ts index 952056ab294..a65b66cef18 100644 --- a/extensions/codex/src/app-server/rate-limits.ts +++ b/extensions/codex/src/app-server/rate-limits.ts @@ -499,12 +499,12 @@ function formatRelativeDuration(durationMs: number): string { } function formatResetDuration(resetsAtMs: number, nowMs: number): string { - const safeMs = Math.max(ONE_SECOND_MS, resetsAtMs - nowMs); - const totalSeconds = Math.round(safeMs / ONE_SECOND_MS); - const days = Math.floor(totalSeconds / 86_400); - const hours = Math.floor((totalSeconds % 86_400) / 3600); - const minutes = Math.floor((totalSeconds % 3600) / 60); - const seconds = totalSeconds % 60; + const durationMs = + Math.round(Math.max(ONE_SECOND_MS, resetsAtMs - nowMs) / ONE_SECOND_MS) * ONE_SECOND_MS; + const days = Math.floor(durationMs / ONE_DAY_MS); + const hours = Math.floor((durationMs % ONE_DAY_MS) / ONE_HOUR_MS); + const minutes = Math.floor((durationMs % ONE_HOUR_MS) / ONE_MINUTE_MS); + const seconds = Math.floor((durationMs % ONE_MINUTE_MS) / ONE_SECOND_MS); if (days > 0) { return hours > 0 ? `${days}d ${hours}h` : `${days}d`; }