feat: surface oauth quota details

This commit is contained in:
ciat-777
2026-03-18 12:42:31 +08:00
parent cd37b11722
commit f902fe1cf6
9 changed files with 578 additions and 3 deletions
@@ -1,4 +1,5 @@
import { schema } from '../../db/index.js';
import type { OauthQuotaSnapshot } from './quotaTypes.js';
type ParsedOauthInfo = {
provider?: unknown;
@@ -11,6 +12,7 @@ type ParsedOauthInfo = {
refreshToken?: unknown;
idToken?: unknown;
providerData?: unknown;
quota?: unknown;
modelDiscoveryStatus?: unknown;
lastModelSyncAt?: unknown;
lastModelSyncError?: unknown;
@@ -34,6 +36,7 @@ export type OauthInfo = {
refreshToken?: string;
idToken?: string;
providerData?: Record<string, unknown>;
quota?: OauthQuotaSnapshot;
modelDiscoveryStatus?: OauthModelDiscoveryStatus;
lastModelSyncAt?: string;
lastModelSyncError?: string;
@@ -88,6 +91,11 @@ function asRecord(value: unknown): Record<string, unknown> | undefined {
return value as Record<string, unknown>;
}
function asQuotaSnapshot(value: unknown): OauthQuotaSnapshot | undefined {
if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;
return value as OauthQuotaSnapshot;
}
function asModelDiscoveryStatus(value: unknown): OauthModelDiscoveryStatus | undefined {
if (typeof value !== 'string') return undefined;
const normalized = value.trim().toLowerCase();
@@ -113,6 +121,7 @@ export function getOauthInfoFromExtraConfig(extraConfig?: string | null): OauthI
refreshToken: asTrimmedString(parsed.refreshToken),
idToken: asTrimmedString(parsed.idToken),
providerData: asRecord(parsed.providerData),
quota: asQuotaSnapshot(parsed.quota),
modelDiscoveryStatus: asModelDiscoveryStatus(parsed.modelDiscoveryStatus),
lastModelSyncAt: asIsoDateTime(parsed.lastModelSyncAt),
lastModelSyncError: asTrimmedString(parsed.lastModelSyncError),
+7
View File
@@ -16,6 +16,7 @@ import {
} from './providers.js';
import { buildOauthInfo, getOauthInfoFromExtraConfig } from './oauthAccount.js';
import { buildCodexOauthInfo } from './codexAccount.js';
import { buildQuotaSnapshotFromOauthInfo, refreshOauthQuotaSnapshot } from './quota.js';
type OAuthProviderMetadata = ReturnType<typeof listOauthProviders>[number];
const MANUAL_CALLBACK_DELAY_MS = 15_000;
@@ -503,6 +504,7 @@ export async function listOauthConnections(options: {
projectId: oauth.projectId,
modelCount: models.length,
modelsPreview: models.slice(0, 10),
quota: buildQuotaSnapshotFromOauthInfo(oauth),
status,
routeChannelCount: routeChannelCountByAccount.get(row.accounts.id) || 0,
lastModelSyncAt: oauth.lastModelSyncAt,
@@ -535,6 +537,11 @@ export async function deleteOauthConnection(accountId: number) {
return { success: true };
}
export async function refreshOauthConnectionQuota(accountId: number) {
const quota = await refreshOauthQuotaSnapshot(accountId);
return { success: true, quota };
}
export async function startOauthRebindFlow(accountId: number, requestOrigin?: string) {
const account = await db.select().from(schema.accounts)
.where(eq(schema.accounts.id, accountId))