diff --git a/src/providers/quota.ts b/src/providers/quota.ts index 29a57c452a..bb3bab2837 100644 --- a/src/providers/quota.ts +++ b/src/providers/quota.ts @@ -237,21 +237,27 @@ function providerLabel(providerId: string): string { } function normalizeResetAt(value: unknown): number | undefined { - if (typeof value === "number" && Number.isFinite(value)) return value > 10_000_000_000 ? value : value * 1000; + if (typeof value === "number" && Number.isFinite(value)) return epochMillis(value); if (typeof value === "string" && value.trim()) { const trimmed = value.trim(); // Cursor Connect RPC returns billingCycleEnd as a unix-ms decimal string ("1771077734000"). // Date.parse treats that as invalid; numeric epoch strings must be handled explicitly. - if (/^\d+(\.\d+)?$/.test(trimmed)) { + if (/^[+-]?\d+(\.\d+)?$/.test(trimmed)) { const numeric = Number(trimmed); - if (Number.isFinite(numeric)) return numeric > 10_000_000_000 ? numeric : numeric * 1000; + return epochMillis(numeric); } const parsed = Date.parse(trimmed); - return Number.isFinite(parsed) ? parsed : undefined; + return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined; } return undefined; } +/** Unix 0 / negative values are sentinels, not reset clocks (Command Code fiveHour.resetAt: 0). */ +function epochMillis(value: number): number | undefined { + if (!Number.isFinite(value) || value <= 0) return undefined; + return value > 10_000_000_000 ? value : value * 1000; +} + function toFiniteNumber(value: unknown): number | undefined { if (typeof value === "number" && Number.isFinite(value)) return value; if (typeof value === "string" && value.trim()) { diff --git a/tests/command-code-quota.test.ts b/tests/command-code-quota.test.ts index e840bb8dd3..3e8da6d0d3 100644 --- a/tests/command-code-quota.test.ts +++ b/tests/command-code-quota.test.ts @@ -118,6 +118,66 @@ describe("Command Code provider quota", () => { expect(JSON.stringify(result)).not.toContain("commandcode-secret"); }); + test("omits a zero Command Code window reset instead of treating it as the Unix epoch", async () => { + globalThis.fetch = (async (input: RequestInfo | URL) => { + const url = String(input); + if (url === "https://api.commandcode.ai/alpha/whoami" + || url === "https://api.commandcode.ai/alpha/billing/subscriptions" + || url === "https://api.commandcode.ai/alpha/usage/summary") { + return new Response("down", { status: 500 }); + } + if (url !== "https://api.commandcode.ai/alpha/billing/credits") { + throw new Error(`unexpected Command Code quota probe: ${url}`); + } + return new Response(JSON.stringify({ + windowLimits: { + fiveHour: { cap: 14, used: 0, resetAt: 0 }, + weekly: { cap: 35, used: 34.9522404823, resetAt: 1_787_184_801_319 }, + }, + }), { status: 200, headers: { "content-type": "application/json" } }); + }) as typeof fetch; + + const result = await fetchProviderQuotaReports(commandCodeConfig(), true); + + expect(result.reports[0]?.quota).toEqual({ + fiveHourPercent: 0, + weeklyPercent: 99.86354423514285, + weeklyResetAt: 1_787_184_801_319, + updatedAt: expect.any(Number), + }); + expect(result.reports[0]?.quota).not.toHaveProperty("fiveHourResetAt"); + }); + + test("omits a signed numeric Command Code window reset instead of Date.parse-ing it", async () => { + globalThis.fetch = (async (input: RequestInfo | URL) => { + const url = String(input); + if (url === "https://api.commandcode.ai/alpha/whoami" + || url === "https://api.commandcode.ai/alpha/billing/subscriptions" + || url === "https://api.commandcode.ai/alpha/usage/summary") { + return new Response("down", { status: 500 }); + } + if (url !== "https://api.commandcode.ai/alpha/billing/credits") { + throw new Error(`unexpected Command Code quota probe: ${url}`); + } + return new Response(JSON.stringify({ + windowLimits: { + fiveHour: { cap: 14, used: 0, resetAt: "-1" }, + weekly: { cap: 35, used: 34.9522404823, resetAt: 1_787_184_801_319 }, + }, + }), { status: 200, headers: { "content-type": "application/json" } }); + }) as typeof fetch; + + const result = await fetchProviderQuotaReports(commandCodeConfig(), true); + + expect(result.reports[0]?.quota).toEqual({ + fiveHourPercent: 0, + weeklyPercent: 99.86354423514285, + weeklyResetAt: 1_787_184_801_319, + updatedAt: expect.any(Number), + }); + expect(result.reports[0]?.quota).not.toHaveProperty("fiveHourResetAt"); + }); + test("keeps rolling windows when whoami and usage summary fail", async () => { const seen: string[] = []; globalThis.fetch = (async (input: RequestInfo | URL) => {