fix: remove AI credit refresh time scraping

This commit is contained in:
Draculabo committed 2026-04-19 01:10:51 +08:00
1 parent 7093c982ba
commit 3e1e10b2a5
5 files changed
+52 -35

No files matched your search

+23 -25
View File
@@ -29,6 +29,7 @@ import { useProviderGrouping } from '@/hooks/useProviderGrouping';
import { ProviderGroup } from '@/components/ProviderGroup'; import { ProviderGroup } from '@/components/ProviderGroup';
import { import {
clampQuotaPercentage, clampQuotaPercentage,
formatAiCreditsAmount,
formatResetTimeLabel, formatResetTimeLabel,
formatResetTimeTitle, formatResetTimeTitle,
getQuotaStatus, getQuotaStatus,
@@ -82,6 +83,19 @@ function isGeminiProHighModel(modelName: string): boolean {
return normalizedModelName.includes('gemini-3.1-pro-high'); 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 { function isGeminiProFamilyModel(modelName: string): boolean {
const normalizedModelName = modelName.toLowerCase(); const normalizedModelName = modelName.toLowerCase();
return normalizedModelName.includes('gemini-3.1-pro'); return normalizedModelName.includes('gemini-3.1-pro');
@@ -325,17 +339,8 @@ export function CloudAccountCard({
); );
const aiCredits = account.quota?.ai_credits; const aiCredits = account.quota?.ai_credits;
const shouldShowAiCredits = !!aiCredits && Number.isFinite(aiCredits.credits) && aiCredits.credits >= 0; 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 validationBlockedStatusLabel = getValidationBlockedStatusLabel( const validationBlockedStatusLabel = getValidationBlockedStatusLabel(
account.status, account.status,
@@ -379,7 +384,7 @@ export function CloudAccountCard({
{shouldShowAiCredits && aiCredits && ( {shouldShowAiCredits && aiCredits && (
<div className="mt-1 flex items-center gap-1 text-[10px] font-medium text-amber-500"> <div className="mt-1 flex items-center gap-1 text-[10px] font-medium text-amber-500">
<span>${aiCredits.credits.toFixed(2)}</span> <span>{formatAiCreditsAmount(aiCredits.credits)}</span>
{aiCredits.expiryDate && ( {aiCredits.expiryDate && (
<span className="text-muted-foreground opacity-70"> <span className="text-muted-foreground opacity-70">
·{' '} ·{' '}
@@ -635,17 +640,8 @@ export function CompactCloudAccountCard({
); );
const aiCredits = account.quota?.ai_credits; const aiCredits = account.quota?.ai_credits;
const shouldShowAiCredits = !!aiCredits && Number.isFinite(aiCredits.credits) && aiCredits.credits >= 0; 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 validationBlockedStatusLabel = getValidationBlockedStatusLabel( const validationBlockedStatusLabel = getValidationBlockedStatusLabel(
account.status, account.status,
@@ -695,12 +691,14 @@ export function CompactCloudAccountCard({
<div className="text-muted-foreground flex items-center gap-3 text-xs"> <div className="text-muted-foreground flex items-center gap-3 text-xs">
<span className="truncate">{account.email}</span> <span className="truncate">{account.email}</span>
{validationBlockedStatusLabel && ( {validationBlockedStatusLabel && (
<span className="text-destructive shrink-0 font-medium">{validationBlockedStatusLabel}</span> <span className="text-destructive shrink-0 font-medium">
{validationBlockedStatusLabel}
</span>
)} )}
{shouldShowAiCredits && aiCredits && ( {shouldShowAiCredits && aiCredits && (
<span className="shrink-0 text-amber-500"> <span className="shrink-0 text-amber-500">
${aiCredits.credits.toFixed(2)} {formatAiCreditsAmount(aiCredits.credits)}
{aiCredits.expiryDate && ( {aiCredits.expiryDate && (
<span className="text-muted-foreground"> <span className="text-muted-foreground">
{' '} {' '}
+2 -1
View File
@@ -74,6 +74,7 @@ import {
import { filter, flatMap, isEmpty, isNumber, size, sumBy } from 'lodash-es'; import { filter, flatMap, isEmpty, isNumber, size, sumBy } from 'lodash-es';
import { import {
clampQuotaPercentage, clampQuotaPercentage,
formatAiCreditsAmount,
getQuotaStatus, getQuotaStatus,
roundQuotaPercentage, roundQuotaPercentage,
getAccountSortValue, getAccountSortValue,
@@ -317,7 +318,7 @@ export function CloudAccountList() {
toast({ toast({
title: t('cloud.toast.quotaRefreshed'), title: t('cloud.toast.quotaRefreshed'),
description: t('cloud.toast.refreshCreditsAvailable', { description: t('cloud.toast.refreshCreditsAvailable', {
amount: credits.toFixed(2), amount: formatAiCreditsAmount(credits),
}), }),
}); });
return; return;
+20 -5
View File
@@ -54,7 +54,10 @@ function normalizeProjectId(projectId?: string): string | null {
return normalized === '' ? null : normalized; 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); const classified = classifyAccountStatusFromError(error);
if (!classified || classified.status !== 'rate_limited') { if (!classified || classified.status !== 'rate_limited') {
return null; return null;
@@ -148,7 +151,10 @@ async function clearAccountStatus(account: CloudAccount): Promise<void> {
} }
function hydrateActiveOAuthClientFromSettings(): void { function hydrateActiveOAuthClientFromSettings(): void {
const preferredClientKey = CloudAccountRepo.getSetting<string>(ACTIVE_OAUTH_CLIENT_KEY_SETTING, ''); const preferredClientKey = CloudAccountRepo.getSetting<string>(
ACTIVE_OAUTH_CLIENT_KEY_SETTING,
'',
);
if (isString(preferredClientKey) && !isEmpty(preferredClientKey.trim())) { if (isString(preferredClientKey) && !isEmpty(preferredClientKey.trim())) {
try { try {
GoogleAPIService.setActiveOAuthClientKey(preferredClientKey); GoogleAPIService.setActiveOAuthClientKey(preferredClientKey);
@@ -165,7 +171,10 @@ function hydrateActiveOAuthClientFromSettings(): void {
async function backfillMissingOAuthClientKeyForLegacyAccounts( async function backfillMissingOAuthClientKeyForLegacyAccounts(
accounts: CloudAccount[], accounts: CloudAccount[],
): Promise<boolean> { ): Promise<boolean> {
const backfillDone = CloudAccountRepo.getSetting<boolean>(OAUTH_CLIENT_KEY_BACKFILL_DONE_SETTING, false); const backfillDone = CloudAccountRepo.getSetting<boolean>(
OAUTH_CLIENT_KEY_BACKFILL_DONE_SETTING,
false,
);
if (backfillDone) { if (backfillDone) {
return false; return false;
} }
@@ -282,7 +291,10 @@ export async function addGoogleAccount(
try { try {
const quota = await GoogleAPIService.fetchQuota(account.token.access_token); const quota = await GoogleAPIService.fetchQuota(account.token.access_token);
try { try {
const aiCredits = await GoogleAPIService.fetchAICredits(account.token.access_token); const aiCredits = await GoogleAPIService.fetchAICredits(
account.token.access_token,
undefined,
);
if (aiCredits) { if (aiCredits) {
quota.ai_credits = aiCredits; quota.ai_credits = aiCredits;
} else { } else {
@@ -708,7 +720,10 @@ export function getActiveOAuthClient(): string {
export function setActiveOAuthClient(clientKey: string): void { export function setActiveOAuthClient(clientKey: string): void {
GoogleAPIService.setActiveOAuthClientKey(clientKey); 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<string> { export async function exportCloudAccounts(stripTokens = false): Promise<string> {
+1 -4
View File
@@ -33,9 +33,6 @@ const QUOTA_API_ENDPOINTS = [
'https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels', 'https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels',
] as const; ] as const;
// Internal API masquerading
const USER_AGENT = 'antigravity/1.11.3 Darwin/arm64';
// Request timeout in milliseconds (30 seconds) // Request timeout in milliseconds (30 seconds)
const REQUEST_TIMEOUT_MS = 30000; const REQUEST_TIMEOUT_MS = 30000;
@@ -898,7 +895,7 @@ export class GoogleAPIService {
const fallbackData = (await fallbackResponse.json()) as LoadProjectResponse; const fallbackData = (await fallbackResponse.json()) as LoadProjectResponse;
return extractAiCreditsFromProjectContext(fallbackData); return extractAiCreditsFromProjectContext(fallbackData);
} catch (e) { } catch {
return null; return null;
} }
} }
+6
View File
@@ -31,6 +31,12 @@ export function roundQuotaPercentage(value: number): number {
return Math.round(value * 10) / 10; 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 { export function formatTimeRemaining(dateStr: string): string | null {
const targetDate = new Date(dateStr); const targetDate = new Date(dateStr);
if (Number.isNaN(targetDate.getTime())) { if (Number.isNaN(targetDate.getTime())) {