fix: bind Codex reset snapshots to accounts

This commit is contained in:
joshrzemien
2026-07-28 03:11:35 -04:00
parent 74debff579
commit 93b17a2f17
2 changed files with 60 additions and 11 deletions
@@ -962,10 +962,8 @@ export class StatusLineComponent implements Component {
return this.#vibeWorkerTokenRate?.() ?? null;
}
#getUsageContextKey(session: AgentSession): string {
const activeProvider = session.state.model?.provider ?? session.model?.provider ?? "";
#formatUsageContextKey(activeProvider: string | undefined, identity: OAuthAccountIdentity | undefined): string {
if (!activeProvider) return "";
const identity = session.modelRegistry?.authStorage?.getOAuthAccountIdentity(activeProvider, session.sessionId);
// orgId is part of the key: rotating between two same-email Anthropic
// subscriptions must invalidate the cached usage immediately instead of
// showing the previous org's quota for the rest of the cache TTL.
@@ -978,6 +976,14 @@ export class StatusLineComponent implements Component {
].join("\0");
}
#getUsageContextKey(session: AgentSession): string {
const activeProvider = session.state.model?.provider ?? session.model?.provider;
const identity = activeProvider
? session.modelRegistry?.authStorage?.getOAuthAccountIdentity(activeProvider, session.sessionId)
: undefined;
return this.#formatUsageContextKey(activeProvider, identity);
}
/**
* Startup redraws only arm a short-delayed task; timeout releases the render
* cadence while a late successful fetch can still refresh the cached segment.
@@ -1042,7 +1048,7 @@ export class StatusLineComponent implements Component {
this.#cachedUsage = normalized;
this.#usageFetchedAt = Date.now();
if (activeProvider !== "openai-codex" || !normalized) return;
const contextKey = this.#getUsageContextKey(session);
const contextKey = this.#formatUsageContextKey(activeProvider, activeIdentity);
const previous = this.#codexResetSnapshots.get(contextKey);
this.#codexResetSnapshots.set(contextKey, normalized);
if (!previous || !settings.get("tui.codexResetFireworks")) return;
@@ -65,8 +65,7 @@ interface CodexUsageState {
omitFetchedAt?: boolean;
}
function codexUsageReport(state: CodexUsageState): unknown[] {
const accountId = "account-1";
function codexUsageReport(state: CodexUsageState, accountId = "account-1"): unknown[] {
return [
{
provider: "openai-codex",
@@ -90,7 +89,13 @@ function codexUsageReport(state: CodexUsageState): unknown[] {
];
}
function makeCodexSession(fetchUsageReports: (signal?: AbortSignal) => Promise<unknown>): AgentSession {
function makeCodexSession(
fetchUsageReports: (signal?: AbortSignal) => Promise<unknown>,
resolveActiveIdentity: () => { accountId: string; email?: string } = () => ({
accountId: "account-1",
email: "codex@example.com",
}),
): AgentSession {
const session = makeSession(fetchUsageReports) as unknown as Record<string, unknown>;
session.sessionId = "session-1";
session.state = {
@@ -100,10 +105,7 @@ function makeCodexSession(fetchUsageReports: (signal?: AbortSignal) => Promise<u
session.model = { contextWindow: 200_000, provider: "openai-codex" };
session.modelRegistry = {
authStorage: {
getOAuthAccountIdentity: () => ({
accountId: "account-1",
email: "codex@example.com",
}),
getOAuthAccountIdentity: resolveActiveIdentity,
},
};
return session as unknown as AgentSession;
@@ -323,6 +325,47 @@ describe("StatusLineComponent usage refresh", () => {
component.dispose();
});
it("binds each reset snapshot to the account identity used to normalize it", async () => {
Settings.instance.set("tui.codexResetFireworks", true);
const sevenDayResetAt = Date.now() + 80 * 3_600_000;
const reports = [
...codexUsageReport(
{
sevenDayPercent: 18,
sevenDayResetAt,
savedResets: 0,
},
"account-a",
),
...codexUsageReport(
{
sevenDayPercent: 22,
sevenDayResetAt,
savedResets: 1,
},
"account-b",
),
];
const identityLookups: string[] = [];
const component = new StatusLineComponent(
makeCodexSession(
async () => reports,
() => ({ accountId: identityLookups.shift() ?? "account-a" }),
),
);
const events: CodexResetFireworksEvent[] = [];
component.setCodexResetFireworksHandler(event => events.push(event));
await refreshUsage(component);
// The refresh starts under A, but B is active when its report is normalized.
// A later identity lookup must not attribute B's saved reset to A.
identityLookups.push("account-a", "account-b", "account-a");
await refreshUsage(component, 5 * 60_000);
expect(events).toEqual([]);
component.dispose();
});
it("keeps an unavailable saved-reset count unknown across refreshes", async () => {
Settings.instance.set("tui.codexResetFireworks", true);
const sevenDayResetAt = Date.now() + 80 * 3_600_000;