fix(codex): preserve quota window duration (#9222)

Validated in local merge-train (devbox-vm-06-dev002) @ combined-tip (FAST gates — only pre-existing audit.test.ts flake).
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-08-05 22:40:33 -03:00
committed by GitHub
parent 348e1b1921
commit bfd2d5603c
3 changed files with 76 additions and 5 deletions

View File

@@ -0,0 +1 @@
- **fix(codex):** preserve quota window duration in usage shape. (thanks @HectorBernstorff)

View File

@@ -13,6 +13,7 @@ export type CodexUsageQuota = {
remaining?: number;
resetAt: string | null;
unlimited: boolean;
windowSeconds: number | null;
displayName?: string;
};
@@ -38,6 +39,15 @@ function toNumber(value: unknown, fallback = 0): number {
return fallback;
}
function toNullableNumber(value: unknown): number | null {
if (typeof value === "number" && Number.isFinite(value)) return value;
if (typeof value === "string" && value.trim().length > 0) {
const parsed = Number(value);
return Number.isFinite(parsed) ? parsed : null;
}
return null;
}
function parseResetTime(resetValue: unknown): string | null {
if (!resetValue) return null;
try {
@@ -81,6 +91,15 @@ function buildPercentageQuota(window: JsonRecord, displayName?: string): CodexUs
remaining: 100 - usedPercent,
resetAt: parseWindowReset(window),
unlimited: false,
windowSeconds: toNullableNumber(
getFieldValue(
window,
"limit_window_seconds",
"limitWindowSeconds",
"window_seconds",
"windowSeconds"
)
),
...(displayName ? { displayName } : {}),
};
}
@@ -105,10 +124,7 @@ function isLatentWindow(window: JsonRecord): boolean {
getFieldValue(window, "limit_window_seconds", "limitWindowSeconds"),
0
);
const resetAfter = toNumber(
getFieldValue(window, "reset_after_seconds", "resetAfterSeconds"),
0
);
const resetAfter = toNumber(getFieldValue(window, "reset_after_seconds", "resetAfterSeconds"), 0);
return usedPercent === 0 && limitWindow > 0 && resetAfter >= limitWindow;
}
@@ -225,7 +241,9 @@ function findCodexReviewRateLimit(data: JsonRecord): JsonRecord {
* (issue #5199).
*/
function parseBankedResetCredits(data: JsonRecord): number | undefined {
const resetCredits = toRecord(getFieldValue(data, "rate_limit_reset_credits", "rateLimitResetCredits"));
const resetCredits = toRecord(
getFieldValue(data, "rate_limit_reset_credits", "rateLimitResetCredits")
);
const availableCount = getFieldValue(resetCredits, "available_count", "availableCount");
const count = toNumber(availableCount, NaN);
return Number.isFinite(count) ? count : undefined;

View File

@@ -0,0 +1,52 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import { buildCodexUsageQuotas } from "../../open-sse/services/codexUsageQuotas";
describe("Codex usage windows", () => {
it("preserves upstream durations for session and weekly windows", () => {
const { quotas } = buildCodexUsageQuotas({
rate_limit: {
primary_window: {
used_percent: 7,
limit_window_seconds: 18_000,
reset_at: 1_785_623_016,
},
secondary_window: {
used_percent: 19,
limit_window_seconds: 604_800,
reset_at: 1_785_678_428,
},
},
});
assert.deepEqual(quotas.session, {
used: 7,
total: 100,
remaining: 93,
resetAt: new Date(1_785_623_016_000).toISOString(),
unlimited: false,
windowSeconds: 18_000,
});
assert.deepEqual(quotas.weekly, {
used: 19,
total: 100,
remaining: 81,
resetAt: new Date(1_785_678_428_000).toISOString(),
unlimited: false,
windowSeconds: 604_800,
});
});
it("accepts camelCase duration variants and nulls invalid values", () => {
const { quotas } = buildCodexUsageQuotas({
rateLimit: {
primaryWindow: { usedPercent: 3, windowSeconds: "18000" },
secondaryWindow: { usedPercent: 4, windowSeconds: "not-a-number" },
},
});
assert.equal(quotas.session.windowSeconds, 18_000);
assert.equal(quotas.weekly.windowSeconds, null);
});
});