feat(provider): support Codex subscriptions with ChatGPT sign-in (#2513)

* feat(provider): support Codex subscriptions with ChatGPT sign-in

* style: format Codex live integration test

* fix(provider): preserve Codex identity in temporary model tests

* fix(web): portal provider selector without dialog overflow

* fix(web): allow native scrolling in provider dropdown

* fix(provider): surface safe Codex quota and upstream errors

* fix(web): provide reliable Codex copy feedback in dialogs

* feat(provider): confirm cascade deletion from edit dialog

* fix(persistence): discard connections after failed commit

* fix(web): polish provider loading and confirmation motion

---------

Co-authored-by: dadachann <185672915+dadachann@users.noreply.github.com>
This commit is contained in:
Hyu
2026-09-06 23:31:02 +08:00
committed by GitHub
parent ec63978ecf
commit 0f216a0d4d
52 changed files with 5490 additions and 360 deletions
+51 -2
View File
@@ -1,4 +1,9 @@
import { BaseHttpClient, type RequestConfig } from './BaseHttpClient';
import type {
CodexAuthStatus,
CodexDeviceAuthorization,
CodexDevicePoll,
} from '@/app/infra/entities/codex';
import {
ApiRespProviderRequesters,
ApiRespProviderRequester,
@@ -126,8 +131,52 @@ export class BackendClient extends BaseHttpClient {
return this.put(`/api/v1/provider/providers/${uuid}`, provider);
}
public deleteModelProvider(uuid: string): Promise<object> {
return this.delete(`/api/v1/provider/providers/${uuid}`);
public deleteModelProvider(uuid: string, cascade = false): Promise<object> {
return this.delete(
`/api/v1/provider/providers/${uuid}${cascade ? '?cascade=true' : ''}`,
);
}
public getCodexAuthStatus(
uuid: string,
signal?: AbortSignal,
): Promise<CodexAuthStatus> {
return this.get(
`/api/v1/provider/providers/${uuid}/codex/status`,
undefined,
{ signal },
);
}
public startCodexDeviceLogin(
uuid: string,
): Promise<CodexDeviceAuthorization> {
return this.post(`/api/v1/provider/providers/${uuid}/codex/device`, {});
}
public pollCodexDeviceLogin(
uuid: string,
authorizationId: string,
signal?: AbortSignal,
): Promise<CodexDevicePoll> {
return this.post(
`/api/v1/provider/providers/${uuid}/codex/device/poll`,
{ authorization_id: authorizationId },
{ signal },
);
}
public cancelCodexDeviceLogin(
uuid: string,
authorizationId: string,
): Promise<object> {
return this.delete(
`/api/v1/provider/providers/${uuid}/codex/device/${encodeURIComponent(authorizationId)}`,
);
}
public disconnectCodex(uuid: string): Promise<object> {
return this.delete(`/api/v1/provider/providers/${uuid}/codex/auth`);
}
public scanProviderModels(