feat: surface oauth quota details
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user