Skip to content
Closed
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
9 changes: 6 additions & 3 deletions src/codex/auth-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,15 @@ function codexAccountPersistenceConflict(
}

/**
* The exact label `parseUsageQuota` emits for the Codex Spark window (quota.ts).
* The exact labels `parseUsageQuota` emits for the Codex Spark windows (quota.ts).
* Matching on the label rather than on "is a custom window" is load-bearing: the same array
* carries Cursor's First-party models / API usage, Anthropic's Fable / Opus / Sonnet,
* Antigravity's Gem / Cla, Kimi's subscription credits and a dozen dynamic provider meters.
*/
const CODEX_SPARK_WINDOW_LABEL = "GPT-5.3-Codex-Spark Weekly";
const CODEX_SPARK_WINDOW_LABELS = new Set([
"GPT-5.3-Codex-Spark 5h",
"GPT-5.3-Codex-Spark Weekly",
]);

/**
* Drop the Spark window unless the operator asked for it (default hidden).
Expand All @@ -264,7 +267,7 @@ export function withSparkVisibility<T extends Omit<StoredAccountQuota, "updatedA
): T {
if (!quota?.customWindows?.length) return quota;
if (loadConfig().showCodexSparkQuota === true) return quota;
const kept = quota.customWindows.filter(window => window.label !== CODEX_SPARK_WINDOW_LABEL);
const kept = quota.customWindows.filter(window => !CODEX_SPARK_WINDOW_LABELS.has(window.label));
if (kept.length === quota.customWindows.length) return quota;
// An empty list is dropped rather than serialized: an absent field and an empty array should
// not be two different ways of saying "no custom windows" on the wire.
Expand Down
23 changes: 15 additions & 8 deletions src/codex/quota.ts
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,10 @@ export function parseUsageQuota(data: WhamUsageResponse): Omit<StoredAccountQuot
});
const sparkWindows = [spark?.rate_limit?.primary_window, spark?.rate_limit?.secondary_window]
.filter((window): window is WhamUsageWindow => !!window);
const sparkShort = sparkWindows.find(window => {
const percent = normalizeUsagePercent(window.used_percent);
return percent !== undefined && isExplicitShortWindow(window);
});
const sparkWeekly = sparkWindows.find(window => {
const percent = normalizeUsagePercent(window.used_percent);
const seconds = window.limit_window_seconds;
Expand All @@ -803,16 +807,19 @@ export function parseUsageQuota(data: WhamUsageResponse): Omit<StoredAccountQuot
&& !isExplicitMonthlyWindow(window)
&& (seconds === undefined || seconds >= WEEKLY_WINDOW_MIN_SECONDS);
});
const sparkPercent = normalizeUsagePercent(sparkWeekly?.used_percent);
if (sparkPercent !== undefined) {
const sparkWindow: { label: string; percent: number; resetAt?: number } = {
label: "GPT-5.3-Codex-Spark Weekly",
percent: sparkPercent,
};
const resetAt = normalizeResetAt(sparkWeekly?.reset_at);
const sparkCustomWindows: Array<{ label: string; percent: number; resetAt?: number }> = [];
for (const [label, window] of [
["GPT-5.3-Codex-Spark 5h", sparkShort],
["GPT-5.3-Codex-Spark Weekly", sparkWeekly],
] as const) {
const percent = normalizeUsagePercent(window?.used_percent);
if (percent === undefined) continue;
const sparkWindow: { label: string; percent: number; resetAt?: number } = { label, percent };
const resetAt = normalizeResetAt(window?.reset_at);
if (resetAt !== undefined) sparkWindow.resetAt = resetAt;
quota.customWindows = [sparkWindow];
sparkCustomWindows.push(sparkWindow);
}
if (sparkCustomWindows.length > 0) quota.customWindows = sparkCustomWindows;
if (resetCredits !== undefined) quota.resetCredits = resetCredits;

return hasKnownQuotaValue(quota) || resetCredits !== undefined ? quota : null;
Expand Down
2 changes: 1 addition & 1 deletion src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ export interface OcxConfig {
*/
codexAccountPickerEnabled?: boolean;
/**
* Show the GPT-5.3-Codex-Spark weekly window on Codex quota surfaces. Default false.
* Show the GPT-5.3-Codex-Spark 5-hour and weekly windows on Codex quota surfaces. Default false.
*
* Spark is a single-model window that reads 0% for most operators, and on a multi-account
* pool it doubles the bar count for information almost nobody acts on. Hidden by default and
Expand Down
11 changes: 8 additions & 3 deletions tests/codex-integration/codex-routing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1746,8 +1746,9 @@ describe("codex routing", () => {
});
});

test("WHAM preserves the 5h, weekly, and Spark weekly windows", () => {
test("WHAM keeps general and Spark windows separate", () => {
expect(parseUsageQuota({
plan_type: "pro",
rate_limit: {
primary_window: { used_percent: 11, reset_at: 1, limit_window_seconds: 5 * 60 * 60 },
secondary_window: { used_percent: 22, reset_at: 2, limit_window_seconds: 7 * 24 * 60 * 60 },
Expand All @@ -1756,7 +1757,8 @@ describe("codex routing", () => {
limit_name: "GPT-5.3-Codex-Spark",
metered_feature: "codex_bengalfox",
rate_limit: {
primary_window: { used_percent: 33, reset_at: 3, limit_window_seconds: 7 * 24 * 60 * 60 },
primary_window: { used_percent: 33, reset_at: 3, limit_window_seconds: 5 * 60 * 60 },
secondary_window: { used_percent: 44, reset_at: 4, limit_window_seconds: 7 * 24 * 60 * 60 },
},
}],
})).toEqual({
Expand All @@ -1765,7 +1767,10 @@ describe("codex routing", () => {
shortWindowSeconds: 5 * 60 * 60,
weeklyPercent: 22,
weeklyResetAt: 2,
customWindows: [{ label: "GPT-5.3-Codex-Spark Weekly", percent: 33, resetAt: 3 }],
customWindows: [
{ label: "GPT-5.3-Codex-Spark 5h", percent: 33, resetAt: 3 },
{ label: "GPT-5.3-Codex-Spark Weekly", percent: 44, resetAt: 4 },
],
});
});

Expand Down
27 changes: 20 additions & 7 deletions tests/codex-integration/codex-spark-visibility.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { OcxConfig } from "../../src/types";
import { removeTreeWithRetry } from "../helpers/remove-tree";

const SPARK = "GPT-5.3-Codex-Spark Weekly";
const SPARK_SHORT = "GPT-5.3-Codex-Spark 5h";
const originalHome = process.env.OPENCODEX_HOME;
let home = "";

Expand All @@ -33,7 +34,7 @@ afterEach(() => {
});

/**
* Codex Spark is a single-model weekly window. It reads 0% for most operators and, on a
* Codex Spark is a single-model quota with 5-hour and weekly windows. It reads 0% for most operators and, on a
* multi-account pool, doubles the bar count on every card for information almost nobody acts
* on — so it is hidden unless the operator asks for it.
*
Expand All @@ -46,33 +47,45 @@ describe("Codex Spark quota visibility", () => {
saveConfig(baseConfig());
const stored = {
weeklyPercent: 11,
customWindows: [{ label: SPARK, percent: 33, resetAt: 3 }],
customWindows: [
{ label: SPARK_SHORT, percent: 33, resetAt: 2 },
{ label: SPARK, percent: 34, resetAt: 3 },
],
updatedAt: Date.now(),
};
const projected = withSparkVisibility(stored);
// Absent, not empty: an absent field and an empty array must not be two different ways of
// saying the same thing on the wire.
expect(projected.customWindows).toBeUndefined();
// The source object is untouched — routing and capacity still see the window.
expect(stored.customWindows).toHaveLength(1);
expect(stored.customWindows).toHaveLength(2);
expect(projected.weeklyPercent).toBe(11);
});

test("an explicit true reveals it unchanged", () => {
saveConfig(baseConfig(true));
loadConfig();
const projected = withSparkVisibility({
customWindows: [{ label: SPARK, percent: 33, resetAt: 3 }],
customWindows: [
{ label: SPARK_SHORT, percent: 33, resetAt: 2 },
{ label: SPARK, percent: 34, resetAt: 3 },
],
updatedAt: Date.now(),
});
expect(projected.customWindows).toEqual([{ label: SPARK, percent: 33, resetAt: 3 }]);
expect(projected.customWindows).toEqual([
{ label: SPARK_SHORT, percent: 33, resetAt: 2 },
{ label: SPARK, percent: 34, resetAt: 3 },
]);
});

test("an explicit false hides it", () => {
saveConfig(baseConfig(false));
loadConfig();
const projected = withSparkVisibility({
customWindows: [{ label: SPARK, percent: 33 }],
customWindows: [
{ label: SPARK_SHORT, percent: 33 },
{ label: SPARK, percent: 34 },
],
updatedAt: Date.now(),
});
expect(projected.customWindows).toBeUndefined();
Expand All @@ -87,6 +100,7 @@ describe("Codex Spark quota visibility", () => {
customWindows: [
{ label: "First-party models", percent: 40 },
{ label: "API usage", percent: 12 },
{ label: SPARK_SHORT, percent: 32 },
{ label: SPARK, percent: 33 },
{ label: "Fable", percent: 7 },
{ label: "Total subscription credits", percent: 90 },
Expand All @@ -112,4 +126,3 @@ describe("Codex Spark quota visibility", () => {
expect(withSparkVisibility(null)).toBeNull();
});
});

Loading