diff --git a/lib/codex-manager.ts b/lib/codex-manager.ts index 8e8d58e4..5fc33786 100644 --- a/lib/codex-manager.ts +++ b/lib/codex-manager.ts @@ -46,6 +46,7 @@ import { runSwitchCommand } from "./codex-manager/commands/switch.js"; import { runVerifyFlaggedCommand, type VerifyFlaggedCliOptions, + type VerifyFlaggedCommandDeps, } from "./codex-manager/commands/verify-flagged.js"; import { applyUiThemeFromDashboardSettings, @@ -2708,31 +2709,6 @@ function upsertRecoveredFlaggedAccount( }; } -async function runVerifyFlagged(args: string[]): Promise { - return runVerifyFlaggedCommand(args, { - setStoragePath, - loadFlaggedAccounts, - loadAccounts, - queuedRefresh, - parseVerifyFlaggedArgs, - printVerifyFlaggedUsage, - createEmptyAccountStorage, - upsertRecoveredFlaggedAccount, - resolveStoredAccountIdentity, - extractAccountId, - extractAccountEmail, - sanitizeEmail, - normalizeFailureDetail, - withAccountAndFlaggedStorageTransaction, - normalizeDoctorIndexes, - saveFlaggedAccounts, - formatAccountLabel, - stylePromptText, - styleAccountDetailText, - formatResultSummary, - }); -} - async function runFix(args: string[]): Promise { if (args.includes("--help") || args.includes("-h")) { printFixUsage(); @@ -3833,6 +3809,31 @@ async function handleManageAction( } } +function buildVerifyFlaggedCommandDeps(): VerifyFlaggedCommandDeps { + return { + setStoragePath, + loadFlaggedAccounts, + loadAccounts, + queuedRefresh, + parseVerifyFlaggedArgs, + printVerifyFlaggedUsage, + createEmptyAccountStorage, + upsertRecoveredFlaggedAccount, + resolveStoredAccountIdentity, + extractAccountId, + extractAccountEmail, + sanitizeEmail, + normalizeFailureDetail, + withAccountAndFlaggedStorageTransaction, + normalizeDoctorIndexes, + saveFlaggedAccounts, + formatAccountLabel, + stylePromptText, + styleAccountDetailText, + formatResultSummary, + }; +} + async function runAuthLogin(args: string[]): Promise { const parsedArgs = parseAuthLoginArgs(args); if (!parsedArgs.ok) { @@ -3961,7 +3962,7 @@ async function runAuthLogin(args: string[]): Promise { "Problem Account Check", "Checking problem accounts", async () => { - await runVerifyFlagged([]); + await runVerifyFlaggedCommand([], buildVerifyFlaggedCommandDeps()); }, displaySettings, ); @@ -4682,7 +4683,7 @@ export async function runCodexMultiAuthCli(rawArgs: string[]): Promise { return runFeaturesCommand({ implementedFeatures: IMPLEMENTED_FEATURES }); } if (command === "verify-flagged") { - return runVerifyFlagged(rest); + return runVerifyFlaggedCommand(rest, buildVerifyFlaggedCommandDeps()); } if (command === "forecast") { return runForecast(rest); diff --git a/test/codex-manager-cli.test.ts b/test/codex-manager-cli.test.ts index 6a6a824d..e961179f 100644 --- a/test/codex-manager-cli.test.ts +++ b/test/codex-manager-cli.test.ts @@ -4733,6 +4733,57 @@ describe("codex manager cli commands", () => { expect(queuedRefreshMock).not.toHaveBeenCalled(); }); + it("runs verify-flagged from the login menu", async () => { + const now = Date.now(); + loadAccountsMock.mockResolvedValue({ + version: 3, + activeIndex: 0, + activeIndexByFamily: { codex: 0 }, + accounts: [ + { + email: "a@example.com", + accountId: "acc_a", + refreshToken: "refresh-a", + accessToken: "access-a", + expiresAt: now + 3_600_000, + addedAt: now - 1_000, + lastUsed: now - 1_000, + enabled: true, + }, + ], + }); + loadFlaggedAccountsMock.mockResolvedValue({ + version: 1, + accounts: [ + { + refreshToken: "flagged-refresh", + accountId: "acc_flagged", + email: "flagged@example.com", + addedAt: now - 1_000, + lastUsed: now - 1_000, + flaggedAt: now - 5_000, + }, + ], + }); + promptLoginModeMock + .mockResolvedValueOnce({ mode: "verify-flagged" }) + .mockResolvedValueOnce({ mode: "cancel" }); + queuedRefreshMock.mockResolvedValueOnce({ + type: "failed", + reason: "invalid_grant", + message: "token expired", + }); + const { runCodexMultiAuthCli } = await import("../lib/codex-manager.js"); + + const exitCode = await runCodexMultiAuthCli(["auth", "login"]); + expect(exitCode).toBe(0); + expect(queuedRefreshMock).toHaveBeenCalledTimes(1); + expect(withAccountAndFlaggedStorageTransactionMock).toHaveBeenCalledTimes( + 1, + ); + expect(saveFlaggedAccountsMock).toHaveBeenCalledTimes(1); + }); + it("auto-refreshes cached limits on menu open", async () => { const now = Date.now(); loadAccountsMock.mockResolvedValue({