Skip to content

Commit 155eba0

Browse files
committed
revert: undo accidental pr-70 push to main
1 parent 549c137 commit 155eba0

File tree

2 files changed

+64
-219
lines changed

2 files changed

+64
-219
lines changed

index.ts

Lines changed: 20 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4165,7 +4165,6 @@ while (attempted.size < Math.max(1, accountCount)) {
41654165
async execute() {
41664166
const ui = resolveUiRuntime();
41674167
const storage = await loadAccounts();
4168-
const usageFetchTimeoutMs = getFetchTimeoutMs(loadPluginConfig());
41694168
if (!storage || storage.accounts.length === 0) {
41704169
if (ui.v2Enabled) {
41714170
return [
@@ -4308,28 +4307,16 @@ while (attempted.size < Math.max(1, accountCount)) {
43084307
organizationId: params.organizationId,
43094308
});
43104309
headers.set("accept", "application/json");
4311-
const controller = new AbortController();
4312-
const timeout = setTimeout(() => controller.abort(), usageFetchTimeoutMs);
43134310

4314-
try {
4315-
const response = await fetch(`${CODEX_BASE_URL}/wham/usage`, {
4316-
method: "GET",
4317-
headers,
4318-
signal: controller.signal,
4319-
});
4320-
if (!response.ok) {
4321-
const bodyText = await response.text().catch(() => "");
4322-
throw new Error(bodyText || `HTTP ${response.status}`);
4323-
}
4324-
return (await response.json()) as UsagePayload;
4325-
} catch (error) {
4326-
if (error instanceof Error && error.name === "AbortError") {
4327-
throw new Error(`Usage request timed out after ${usageFetchTimeoutMs}ms`);
4328-
}
4329-
throw error;
4330-
} finally {
4331-
clearTimeout(timeout);
4311+
const response = await fetch(`${CODEX_BASE_URL}/wham/usage`, {
4312+
method: "GET",
4313+
headers,
4314+
});
4315+
if (!response.ok) {
4316+
const bodyText = await response.text().catch(() => "");
4317+
throw new Error(bodyText || `HTTP ${response.status}`);
43324318
}
4319+
return (await response.json()) as UsagePayload;
43334320
};
43344321

43354322
// Deduplicate accounts by refreshToken (same credential = same limits)
@@ -4338,28 +4325,22 @@ while (attempted.size < Math.max(1, accountCount)) {
43384325
for (let i = 0; i < storage.accounts.length; i++) {
43394326
const acct = storage.accounts[i];
43404327
if (!acct) continue;
4341-
const refreshToken = typeof acct.refreshToken === "string" ? acct.refreshToken : "";
4342-
if (refreshToken && seenTokens.has(refreshToken)) continue;
4343-
if (refreshToken) seenTokens.add(refreshToken);
4328+
if (seenTokens.has(acct.refreshToken)) continue;
4329+
seenTokens.add(acct.refreshToken);
43444330
uniqueIndices.push(i);
43454331
}
43464332

43474333
const lines: string[] = ui.v2Enabled
43484334
? [...formatUiHeader(ui, "Codex limits"), ""]
43494335
: [`Codex limits (${uniqueIndices.length} account${uniqueIndices.length === 1 ? "" : "s"}):`, ""];
43504336
const activeIndex = resolveActiveIndex(storage, "codex");
4351-
const activeRefreshToken =
4352-
typeof activeIndex === "number" && activeIndex >= 0 && activeIndex < storage.accounts.length
4353-
? storage.accounts[activeIndex]?.refreshToken
4354-
: undefined;
43554337
let storageChanged = false;
43564338

43574339
for (const i of uniqueIndices) {
43584340
const account = storage.accounts[i];
43594341
if (!account) continue;
43604342
const label = formatCommandAccountLabel(account, i);
4361-
const isActive = i === activeIndex || (!!activeRefreshToken && account.refreshToken === activeRefreshToken);
4362-
const activeSuffix = isActive ? (ui.v2Enabled ? ` ${formatUiBadge(ui, "active", "accent")}` : " [active]") : "";
4343+
const activeSuffix = i === activeIndex ? (ui.v2Enabled ? ` ${formatUiBadge(ui, "active", "accent")}` : " [active]") : "";
43634344

43644345
try {
43654346
let accessToken = account.accessToken;
@@ -4369,34 +4350,13 @@ while (attempted.size < Math.max(1, accountCount)) {
43694350
typeof account.expiresAt !== "number" ||
43704351
account.expiresAt <= Date.now() + 30_000
43714352
) {
4372-
const previousRefreshToken = account.refreshToken;
43734353
const refreshResult = await queuedRefresh(account.refreshToken);
43744354
if (refreshResult.type !== "success") {
43754355
throw new Error(refreshResult.message ?? refreshResult.reason);
43764356
}
4377-
4378-
const applyRefreshedCredentials = (
4379-
target: {
4380-
refreshToken: string;
4381-
accessToken?: string;
4382-
expiresAt?: number;
4383-
},
4384-
): void => {
4385-
target.refreshToken = refreshResult.refresh;
4386-
target.accessToken = refreshResult.access;
4387-
target.expiresAt = refreshResult.expires;
4388-
};
4389-
4390-
if (previousRefreshToken && refreshResult.refresh !== previousRefreshToken) {
4391-
for (const storedAccount of storage.accounts) {
4392-
if (storedAccount?.refreshToken === previousRefreshToken) {
4393-
applyRefreshedCredentials(storedAccount);
4394-
}
4395-
}
4396-
} else {
4397-
applyRefreshedCredentials(account);
4398-
}
4399-
4357+
account.refreshToken = refreshResult.refresh;
4358+
account.accessToken = refreshResult.access;
4359+
account.expiresAt = refreshResult.expires;
44004360
accessToken = refreshResult.access;
44014361
storageChanged = true;
44024362
}
@@ -4419,7 +4379,7 @@ while (attempted.size < Math.max(1, accountCount)) {
44194379
payload.additional_rate_limits?.find((entry) => entry.limit_name === "code_review_rate_limit")?.rate_limit ??
44204380
null;
44214381
const codeReview = mapWindow(codeReviewRateLimit?.primary_window ?? null);
4422-
const credits = formatCredits(payload.credits ?? null);
4382+
const credits = formatCredits(payload.credits ?? null);
44234383
const additionalLimits = (payload.additional_rate_limits ?? []).filter(
44244384
(entry) => entry.limit_name !== "code_review_rate_limit",
44254385
);
@@ -4475,7 +4435,11 @@ while (attempted.size < Math.max(1, accountCount)) {
44754435

44764436
if (storageChanged) {
44774437
await saveAccounts(storage);
4478-
invalidateAccountManagerCache();
4438+
if (cachedAccountManager) {
4439+
const reloadedManager = await AccountManager.loadFromDisk();
4440+
cachedAccountManager = reloadedManager;
4441+
accountManagerPromise = Promise.resolve(reloadedManager);
4442+
}
44794443
}
44804444

44814445
while (lines.length > 0 && lines[lines.length - 1] === "") {

test/index.test.ts

Lines changed: 44 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,7 @@ describe("OpenAIOAuthPlugin", () => {
763763
});
764764

765765
it("refreshes missing tokens before fetching usage", async () => {
766+
const { saveAccounts } = await import("../lib/storage.js");
766767
mockStorage.accounts = [
767768
{ refreshToken: "r1", accountId: "acc-1", email: "user@example.com" },
768769
];
@@ -782,173 +783,53 @@ describe("OpenAIOAuthPlugin", () => {
782783

783784
expect(result).toContain("100% left");
784785
expect(mockStorage.accounts[0]?.accessToken).toBe("refreshed-access");
786+
expect(saveAccounts).toHaveBeenCalled();
785787
});
786788

787-
it("deduplicates accounts with same refreshToken and keeps the active marker", async () => {
788-
mockStorage.accounts = [
789-
{
790-
refreshToken: "rt_same",
791-
accountId: "acc-1",
792-
email: "a@test.com",
793-
accessToken: "access-1",
794-
expiresAt: Date.now() + 3600_000,
795-
},
796-
{
797-
refreshToken: "rt_same",
798-
accountId: "acc-2",
799-
email: "a@test.com",
800-
accessToken: "access-2",
801-
expiresAt: Date.now() + 3600_000,
802-
},
803-
{
804-
refreshToken: "rt_other",
805-
accountId: "acc-3",
806-
email: "b@test.com",
807-
accessToken: "access-3",
808-
expiresAt: Date.now() + 3600_000,
809-
},
810-
];
811-
mockStorage.activeIndex = 1;
812-
mockStorage.activeIndexByFamily = { codex: 1 };
813-
globalThis.fetch = vi.fn().mockImplementation(async () =>
814-
new Response(
815-
JSON.stringify({
816-
rate_limit: {
817-
primary_window: {
818-
used_percent: 50,
819-
limit_window_seconds: 18000,
820-
reset_at: Math.floor(Date.now() / 1000) + 1800,
821-
},
822-
secondary_window: {
823-
used_percent: 50,
824-
limit_window_seconds: 604800,
825-
reset_at: Math.floor(Date.now() / 1000) + 86400,
826-
},
827-
},
828-
}),
829-
{ status: 200, headers: { "content-type": "application/json" } },
830-
),
831-
);
832-
833-
const result = await plugin.tool["codex-limits"].execute();
834-
835-
expect(result).toContain("2 account");
836-
expect(globalThis.fetch).toHaveBeenCalledTimes(2);
837-
expect(result).toContain("Account 1 (a@test.com, id:acc-1) [active]:");
838-
expect(result.match(/Account 1 \(a@test\.com, id:acc-1\)/g)).toHaveLength(1);
839-
expect(result).toContain("Account 3 (b@test.com, id:acc-3):");
840-
expect(result).not.toContain("Account 2 (a@test.com, id:acc-2):");
841-
});
842-
843-
it("does not deduplicate accounts that are missing refreshToken", async () => {
844-
mockStorage.accounts = [
845-
{
846-
refreshToken: "",
847-
accountId: "acc-1",
848-
email: "missing-1@test.com",
849-
accessToken: "access-1",
850-
expiresAt: Date.now() + 3600_000,
851-
},
852-
{
853-
refreshToken: "",
854-
accountId: "acc-2",
855-
email: "missing-2@test.com",
856-
accessToken: "access-2",
857-
expiresAt: Date.now() + 3600_000,
858-
},
859-
{
860-
refreshToken: "rt_other",
861-
accountId: "acc-3",
862-
email: "other@test.com",
863-
accessToken: "access-3",
864-
expiresAt: Date.now() + 3600_000,
865-
},
866-
];
867-
globalThis.fetch = vi.fn().mockImplementation(async () =>
868-
new Response(
869-
JSON.stringify({
870-
rate_limit: {
871-
primary_window: {
872-
used_percent: 25,
873-
limit_window_seconds: 18000,
874-
reset_at: Math.floor(Date.now() / 1000) + 1800,
875-
},
876-
secondary_window: {
877-
used_percent: 25,
878-
limit_window_seconds: 604800,
879-
reset_at: Math.floor(Date.now() / 1000) + 86400,
880-
},
881-
},
882-
}),
883-
{ status: 200, headers: { "content-type": "application/json" } },
884-
),
885-
);
886-
887-
const result = await plugin.tool["codex-limits"].execute();
888-
889-
expect(result).toContain("3 account");
890-
expect(globalThis.fetch).toHaveBeenCalledTimes(3);
891-
expect(result).toContain("Account 1 (missing-1@test.com, id:acc-1) [active]:");
892-
expect(result).toContain("Account 2 (missing-2@test.com, id:acc-2):");
893-
expect(result).toContain("Account 3 (other@test.com, id:acc-3):");
894-
});
895-
896-
it("propagates rotated refresh tokens to duplicate stored accounts", async () => {
897-
const { queuedRefresh } = await import("../lib/refresh-queue.js");
898-
vi.mocked(queuedRefresh).mockResolvedValueOnce({
899-
type: "success",
900-
access: "rotated-access",
901-
refresh: "rotated-refresh",
902-
expires: Date.now() + 7200_000,
903-
});
904-
mockStorage.accounts = [
905-
{
906-
refreshToken: "stale-refresh",
907-
accountId: "acc-1",
908-
email: "a@test.com",
909-
accessToken: "expired-access-1",
910-
expiresAt: Date.now() - 1000,
911-
},
912-
{
913-
refreshToken: "stale-refresh",
914-
accountId: "acc-2",
915-
email: "a@test.com",
916-
accessToken: "expired-access-2",
917-
expiresAt: Date.now() - 1000,
918-
},
919-
];
920-
globalThis.fetch = vi.fn().mockImplementation(async () =>
921-
new Response(
922-
JSON.stringify({
923-
rate_limit: {
924-
primary_window: {
925-
used_percent: 10,
926-
limit_window_seconds: 18000,
927-
reset_at: Math.floor(Date.now() / 1000) + 1800,
928-
},
929-
secondary_window: {
930-
used_percent: 10,
931-
limit_window_seconds: 604800,
932-
reset_at: Math.floor(Date.now() / 1000) + 86400,
933-
},
934-
},
935-
}),
936-
{ status: 200, headers: { "content-type": "application/json" } },
937-
),
938-
);
789+
it("deduplicates accounts with same refreshToken", async () => {
790+
mockStorage.accounts = [
791+
{
792+
refreshToken: "rt_same",
793+
accountId: "acc-1",
794+
email: "a@test.com",
795+
accessToken: "access-1",
796+
expiresAt: Date.now() + 3600_000,
797+
},
798+
{
799+
refreshToken: "rt_same",
800+
accountId: "acc-2",
801+
email: "a@test.com",
802+
accessToken: "access-2",
803+
expiresAt: Date.now() + 3600_000,
804+
},
805+
{
806+
refreshToken: "rt_other",
807+
accountId: "acc-3",
808+
email: "b@test.com",
809+
accessToken: "access-3",
810+
expiresAt: Date.now() + 3600_000,
811+
},
812+
];
813+
globalThis.fetch = vi.fn().mockResolvedValue(
814+
new Response(
815+
JSON.stringify({
816+
rate_limit: {
817+
primary_window: { used_percent: 50, limit_window_seconds: 18000, reset_at: Math.floor(Date.now() / 1000) + 1800 },
818+
secondary_window: { used_percent: 50, limit_window_seconds: 604800, reset_at: Math.floor(Date.now() / 1000) + 86400 },
819+
},
820+
}),
821+
{ status: 200, headers: { "content-type": "application/json" } },
822+
),
823+
);
939824

940-
await plugin.tool["codex-limits"].execute();
825+
const result = await plugin.tool["codex-limits"].execute();
941826

942-
expect(vi.mocked(queuedRefresh)).toHaveBeenCalledTimes(1);
943-
expect(mockStorage.accounts.map((account) => account.refreshToken)).toEqual([
944-
"rotated-refresh",
945-
"rotated-refresh",
946-
]);
947-
expect(mockStorage.accounts.map((account) => account.accessToken)).toEqual([
948-
"rotated-access",
949-
"rotated-access",
950-
]);
951-
});
827+
expect(result).toBeDefined();
828+
// Header should say "2 accounts" (not 3)
829+
expect(result).toContain("2 account");
830+
// fetch should be called exactly twice (once per unique refreshToken)
831+
expect(globalThis.fetch).toHaveBeenCalledTimes(2);
832+
});
952833
});
953834

954835
describe("codex-metrics tool", () => {

0 commit comments

Comments
 (0)