fix: remove AI credit refresh time scraping
This commit is contained in:
1 parent
7093c982ba
commit
3e1e10b2a5
5 files changed
+52
-35
No files matched your search
@@ -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">
|
||||||
{' '}
|
{' '}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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())) {
|
||||||
|
|||||||
Reference in new issue
Block a user