Skip to content

Commit d9b3358

Browse files
committed
fix(status): use legacy codex oauth for OpenAI usage
1 parent 15361bf commit d9b3358

4 files changed

Lines changed: 60 additions & 10 deletions

File tree

src/infra/provider-usage.auth.normalizes-keys.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,11 @@ const providerRuntimeMocks = vi.hoisted(() => ({
177177
return token?.startsWith("sk-ant-oat01-") ? { token } : { handled: true };
178178
}
179179

180+
if (params.provider === "openai") {
181+
const oauth = await params.context.resolveOAuthToken({ provider: "openai" });
182+
return oauth ?? { handled: true };
183+
}
184+
180185
if (params.provider === "minimax") {
181186
const token = resolveToken({
182187
providerIds: ["minimax"],
@@ -658,6 +663,22 @@ describe("resolveProviderAuths key normalization", () => {
658663
});
659664
});
660665

666+
it("uses legacy openai-codex oauth-compatible profiles for ChatGPT usage auth", async () => {
667+
await expectResolvedAuthsFromSuiteHome({
668+
providers: ["openai"],
669+
setup: async (home) => {
670+
await writeAuthProfiles(home, {
671+
"openai-codex:default": {
672+
type: "token",
673+
provider: "openai-codex",
674+
token: "legacy-chatgpt-token",
675+
},
676+
});
677+
},
678+
expected: [{ provider: "openai", token: "legacy-chatgpt-token" }],
679+
});
680+
});
681+
661682
it("discovers oauth provider from config but skips mismatched profile providers", async () => {
662683
await withSuiteHome(async (home) => {
663684
const config = {

src/infra/provider-usage.auth.ts

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ function resolveUsageCredentialProviderIds(params: {
183183
provider: UsageProviderId;
184184
}): string[] {
185185
const providerIds = new Set(normalizeProviderIds([params.provider]));
186+
if (params.provider === "openai") {
187+
providerIds.add("openai-codex");
188+
}
186189
const providerIdSet = new Set(providerIds);
187190
try {
188191
const snapshot = loadManifestMetadataSnapshot({
@@ -211,6 +214,7 @@ function resolveUsageCredentialProviderIds(params: {
211214
async function resolveOAuthToken(params: {
212215
state: UsageAuthState;
213216
provider: string;
217+
usageProvider?: UsageProviderId;
214218
}): Promise<ProviderAuth | null> {
215219
if (!params.state.allowAuthProfileStore) {
216220
return null;
@@ -241,7 +245,7 @@ async function resolveOAuthToken(params: {
241245
continue;
242246
}
243247
return {
244-
provider: params.provider as UsageProviderId,
248+
provider: params.usageProvider ?? (params.provider as UsageProviderId),
245249
token: resolved.apiKey,
246250
accountId:
247251
cred.type === "oauth" && "accountId" in cred
@@ -278,10 +282,26 @@ async function resolveProviderUsageAuthViaPlugin(params: {
278282
envDirect: options?.envDirect,
279283
}),
280284
resolveOAuthToken: async (options) => {
281-
const auth = await resolveOAuthToken({
282-
state: params.state,
283-
provider: options?.provider ?? params.provider,
284-
});
285+
const requestedProvider = options?.provider;
286+
const providers =
287+
requestedProvider &&
288+
normalizeProviderId(requestedProvider) !== normalizeProviderId(params.provider)
289+
? [requestedProvider]
290+
: resolveUsageCredentialProviderIds({
291+
state: params.state,
292+
provider: params.provider,
293+
});
294+
let auth: ProviderAuth | null = null;
295+
for (const provider of providers) {
296+
auth = await resolveOAuthToken({
297+
state: params.state,
298+
provider,
299+
usageProvider: params.provider,
300+
});
301+
if (auth) {
302+
break;
303+
}
304+
}
285305
return auth
286306
? {
287307
token: auth.token,
@@ -311,12 +331,18 @@ async function resolveProviderUsageAuthFallback(params: {
311331
state: UsageAuthState;
312332
provider: UsageProviderId;
313333
}): Promise<ProviderAuth | null> {
314-
const oauthToken = await resolveOAuthToken({
334+
for (const provider of resolveUsageCredentialProviderIds({
315335
state: params.state,
316336
provider: params.provider,
317-
});
318-
if (oauthToken) {
319-
return oauthToken;
337+
})) {
338+
const oauthToken = await resolveOAuthToken({
339+
state: params.state,
340+
provider,
341+
usageProvider: params.provider,
342+
});
343+
if (oauthToken) {
344+
return oauthToken;
345+
}
320346
}
321347
if (isOAuthOnlyUsageProvider(params.provider)) {
322348
return null;

src/infra/provider-usage.shared.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ describe("provider-usage.shared", () => {
2828
it("maps canonical OpenAI subscription profiles to Codex usage windows", () => {
2929
expect(resolveUsageProviderId("openai", { credentialType: "oauth" })).toBe("openai");
3030
expect(resolveUsageProviderId("openai", { credentialType: "token" })).toBe("openai");
31+
expect(resolveUsageProviderId("openai-codex", { credentialType: "oauth" })).toBe("openai");
32+
expect(resolveUsageProviderId("openai-codex", { credentialType: "token" })).toBe("openai");
3133
expect(resolveUsageProviderId("openai", { credentialType: "api_key" })).toBeUndefined();
34+
expect(resolveUsageProviderId("openai-codex", { credentialType: "api_key" })).toBeUndefined();
3235
});
3336

3437
it.each([

src/infra/provider-usage.shared.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export function resolveUsageProviderId(
4545
}
4646
const normalized = normalizeProviderId(provider);
4747
if (
48-
normalized === "openai" &&
48+
(normalized === "openai" || normalized === "openai-codex") &&
4949
(options?.credentialType === "oauth" || options?.credentialType === "token")
5050
) {
5151
return "openai";

0 commit comments

Comments
 (0)