From 3e1e10b2a580ebf5a64b9a8982bd812a6a1f2924 Mon Sep 17 00:00:00 2001 From: Draculabo Date: Sun, 19 Apr 2026 00:58:01 +0800 Subject: [PATCH] fix: remove AI credit refresh time scraping --- src/components/CloudAccountCard.tsx | 48 ++++++++++++++--------------- src/components/CloudAccountList.tsx | 3 +- src/ipc/cloud/handler.ts | 25 ++++++++++++--- src/services/GoogleAPIService.ts | 5 +-- src/utils/quota-display.ts | 6 ++++ 5 files changed, 52 insertions(+), 35 deletions(-) diff --git a/src/components/CloudAccountCard.tsx b/src/components/CloudAccountCard.tsx index 2253dce..1cb673c 100644 --- a/src/components/CloudAccountCard.tsx +++ b/src/components/CloudAccountCard.tsx @@ -29,6 +29,7 @@ import { useProviderGrouping } from '@/hooks/useProviderGrouping'; import { ProviderGroup } from '@/components/ProviderGroup'; import { clampQuotaPercentage, + formatAiCreditsAmount, formatResetTimeLabel, formatResetTimeTitle, getQuotaStatus, @@ -82,6 +83,19 @@ function isGeminiProHighModel(modelName: string): boolean { return normalizedModelName.includes('gemini-3.1-pro-high'); } +function formatCreditsExpiry(expiryDate: string): string { + if (!expiryDate) { + return ''; + } + + try { + const date = new Date(expiryDate); + return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); + } catch { + return expiryDate; + } +} + function isGeminiProFamilyModel(modelName: string): boolean { const normalizedModelName = modelName.toLowerCase(); return normalizedModelName.includes('gemini-3.1-pro'); @@ -325,17 +339,8 @@ export function CloudAccountCard({ ); const aiCredits = account.quota?.ai_credits; - const shouldShowAiCredits = !!aiCredits && Number.isFinite(aiCredits.credits) && aiCredits.credits >= 0; - - const formatCreditsExpiry = (expiryDate: string) => { - if (!expiryDate) return ''; - try { - const date = new Date(expiryDate); - return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); - } catch { - return expiryDate; - } - }; + const shouldShowAiCredits = + !!aiCredits && Number.isFinite(aiCredits.credits) && aiCredits.credits >= 0; const validationBlockedStatusLabel = getValidationBlockedStatusLabel( account.status, @@ -379,7 +384,7 @@ export function CloudAccountCard({ {shouldShowAiCredits && aiCredits && (
- ${aiCredits.credits.toFixed(2)} + {formatAiCreditsAmount(aiCredits.credits)} {aiCredits.expiryDate && ( ยท{' '} @@ -635,17 +640,8 @@ export function CompactCloudAccountCard({ ); const aiCredits = account.quota?.ai_credits; - const shouldShowAiCredits = !!aiCredits && Number.isFinite(aiCredits.credits) && aiCredits.credits >= 0; - - const formatCreditsExpiry = (expiryDate: string) => { - if (!expiryDate) return ''; - try { - const date = new Date(expiryDate); - return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); - } catch { - return expiryDate; - } - }; + const shouldShowAiCredits = + !!aiCredits && Number.isFinite(aiCredits.credits) && aiCredits.credits >= 0; const validationBlockedStatusLabel = getValidationBlockedStatusLabel( account.status, @@ -695,12 +691,14 @@ export function CompactCloudAccountCard({
{account.email} {validationBlockedStatusLabel && ( - {validationBlockedStatusLabel} + + {validationBlockedStatusLabel} + )} {shouldShowAiCredits && aiCredits && ( - ${aiCredits.credits.toFixed(2)} + {formatAiCreditsAmount(aiCredits.credits)} {aiCredits.expiryDate && ( {' '} diff --git a/src/components/CloudAccountList.tsx b/src/components/CloudAccountList.tsx index 510b370..7940c40 100644 --- a/src/components/CloudAccountList.tsx +++ b/src/components/CloudAccountList.tsx @@ -74,6 +74,7 @@ import { import { filter, flatMap, isEmpty, isNumber, size, sumBy } from 'lodash-es'; import { clampQuotaPercentage, + formatAiCreditsAmount, getQuotaStatus, roundQuotaPercentage, getAccountSortValue, @@ -317,7 +318,7 @@ export function CloudAccountList() { toast({ title: t('cloud.toast.quotaRefreshed'), description: t('cloud.toast.refreshCreditsAvailable', { - amount: credits.toFixed(2), + amount: formatAiCreditsAmount(credits), }), }); return; diff --git a/src/ipc/cloud/handler.ts b/src/ipc/cloud/handler.ts index 03cffbe..87a06b1 100644 --- a/src/ipc/cloud/handler.ts +++ b/src/ipc/cloud/handler.ts @@ -54,7 +54,10 @@ function normalizeProjectId(projectId?: string): string | null { return normalized === '' ? null : normalized; } -function recoverCachedQuotaOnRateLimit(account: CloudAccount, error: unknown): CloudAccount['quota'] | null { +function recoverCachedQuotaOnRateLimit( + account: CloudAccount, + error: unknown, +): CloudAccount['quota'] | null { const classified = classifyAccountStatusFromError(error); if (!classified || classified.status !== 'rate_limited') { return null; @@ -148,7 +151,10 @@ async function clearAccountStatus(account: CloudAccount): Promise { } function hydrateActiveOAuthClientFromSettings(): void { - const preferredClientKey = CloudAccountRepo.getSetting(ACTIVE_OAUTH_CLIENT_KEY_SETTING, ''); + const preferredClientKey = CloudAccountRepo.getSetting( + ACTIVE_OAUTH_CLIENT_KEY_SETTING, + '', + ); if (isString(preferredClientKey) && !isEmpty(preferredClientKey.trim())) { try { GoogleAPIService.setActiveOAuthClientKey(preferredClientKey); @@ -165,7 +171,10 @@ function hydrateActiveOAuthClientFromSettings(): void { async function backfillMissingOAuthClientKeyForLegacyAccounts( accounts: CloudAccount[], ): Promise { - const backfillDone = CloudAccountRepo.getSetting(OAUTH_CLIENT_KEY_BACKFILL_DONE_SETTING, false); + const backfillDone = CloudAccountRepo.getSetting( + OAUTH_CLIENT_KEY_BACKFILL_DONE_SETTING, + false, + ); if (backfillDone) { return false; } @@ -282,7 +291,10 @@ export async function addGoogleAccount( try { const quota = await GoogleAPIService.fetchQuota(account.token.access_token); try { - const aiCredits = await GoogleAPIService.fetchAICredits(account.token.access_token); + const aiCredits = await GoogleAPIService.fetchAICredits( + account.token.access_token, + undefined, + ); if (aiCredits) { quota.ai_credits = aiCredits; } else { @@ -708,7 +720,10 @@ export function getActiveOAuthClient(): string { export function setActiveOAuthClient(clientKey: string): void { GoogleAPIService.setActiveOAuthClientKey(clientKey); - CloudAccountRepo.setSetting(ACTIVE_OAUTH_CLIENT_KEY_SETTING, GoogleAPIService.getActiveOAuthClientKey()); + CloudAccountRepo.setSetting( + ACTIVE_OAUTH_CLIENT_KEY_SETTING, + GoogleAPIService.getActiveOAuthClientKey(), + ); } export async function exportCloudAccounts(stripTokens = false): Promise { diff --git a/src/services/GoogleAPIService.ts b/src/services/GoogleAPIService.ts index a0e34fa..3cd6486 100644 --- a/src/services/GoogleAPIService.ts +++ b/src/services/GoogleAPIService.ts @@ -33,9 +33,6 @@ const QUOTA_API_ENDPOINTS = [ 'https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels', ] as const; -// Internal API masquerading -const USER_AGENT = 'antigravity/1.11.3 Darwin/arm64'; - // Request timeout in milliseconds (30 seconds) const REQUEST_TIMEOUT_MS = 30000; @@ -898,7 +895,7 @@ export class GoogleAPIService { const fallbackData = (await fallbackResponse.json()) as LoadProjectResponse; return extractAiCreditsFromProjectContext(fallbackData); - } catch (e) { + } catch { return null; } } diff --git a/src/utils/quota-display.ts b/src/utils/quota-display.ts index afec1e9..acc469a 100644 --- a/src/utils/quota-display.ts +++ b/src/utils/quota-display.ts @@ -31,6 +31,12 @@ export function roundQuotaPercentage(value: number): number { return Math.round(value * 10) / 10; } +export function formatAiCreditsAmount(credits: number): string { + return new Intl.NumberFormat('en-US', { + maximumFractionDigits: 2, + }).format(credits); +} + export function formatTimeRemaining(dateStr: string): string | null { const targetDate = new Date(dateStr); if (Number.isNaN(targetDate.getTime())) {