Compare commits

..

1 Commits

7 changed files with 134 additions and 15 deletions
+43 -12
View File
@@ -87,7 +87,7 @@ const DEFAULT_ANTIGRAVITY_PROJECT_ID = 'bamboo-precept-lgxtn';
const geminiCliSupplementaryRequestIds = new Map<string, number>();
const geminiCliSupplementaryCache = new Map<
string,
{ requestId: number; tierLabel: string | null; creditBalance: number | null }
{ requestId: number; tierLabel: string | null; tierId: string | null; creditBalance: number | null }
>();
export interface QuotaStore {
@@ -444,6 +444,8 @@ const GEMINI_CLI_TIER_LABELS: Record<string, string> = {
'free-tier': 'tier_free',
'legacy-tier': 'tier_legacy',
'standard-tier': 'tier_standard',
'g1-pro-tier': 'tier_pro',
'g1-ultra-tier': 'tier_ultra',
};
const resolveGeminiCliTierLabel = (
@@ -455,10 +457,23 @@ const resolveGeminiCliTierLabel = (
payload.currentTier ?? payload.current_tier;
const paidTier: GeminiCliUserTier | null | undefined =
payload.paidTier ?? payload.paid_tier;
const tierId = normalizeStringValue(paidTier?.id) ?? normalizeStringValue(currentTier?.id);
if (!tierId) return null;
const rawId = normalizeStringValue(paidTier?.id) ?? normalizeStringValue(currentTier?.id);
if (!rawId) return null;
const tierId = rawId.toLowerCase();
const labelKey = GEMINI_CLI_TIER_LABELS[tierId];
return labelKey ? t(`gemini_cli_quota.${labelKey}`) : tierId;
return labelKey ? t(`gemini_cli_quota.${labelKey}`) : rawId;
};
const resolveGeminiCliTierId = (
payload: GeminiCliCodeAssistPayload | null
): string | null => {
if (!payload) return null;
const currentTier: GeminiCliUserTier | null | undefined =
payload.currentTier ?? payload.current_tier;
const paidTier: GeminiCliUserTier | null | undefined =
payload.paidTier ?? payload.paid_tier;
const rawId = normalizeStringValue(paidTier?.id) ?? normalizeStringValue(currentTier?.id);
return rawId ? rawId.toLowerCase() : null;
};
const resolveGeminiCliCreditBalance = (
@@ -491,7 +506,7 @@ const fetchGeminiCliCodeAssist = async (
authIndex: string,
projectId: string,
t: TFunction
): Promise<{ tierLabel: string | null; creditBalance: number | null }> => {
): Promise<{ tierLabel: string | null; tierId: string | null; creditBalance: number | null }> => {
try {
const result = await apiCallApi.request({
authIndex,
@@ -510,30 +525,32 @@ const fetchGeminiCliCodeAssist = async (
});
if (result.statusCode < 200 || result.statusCode >= 300) {
return { tierLabel: null, creditBalance: null };
return { tierLabel: null, tierId: null, creditBalance: null };
}
const payload = parseGeminiCliCodeAssistPayload(result.body ?? result.bodyText);
return {
tierLabel: resolveGeminiCliTierLabel(payload, t),
tierId: resolveGeminiCliTierId(payload),
creditBalance: resolveGeminiCliCreditBalance(payload),
};
} catch {
return { tierLabel: null, creditBalance: null };
return { tierLabel: null, tierId: null, creditBalance: null };
}
};
const readGeminiCliSupplementarySnapshot = (
fileName: string,
requestId: number
): { tierLabel: string | null; creditBalance: number | null } => {
): { tierLabel: string | null; tierId: string | null; creditBalance: number | null } => {
const cached = geminiCliSupplementaryCache.get(fileName);
if (!cached || cached.requestId !== requestId) {
return { tierLabel: null, creditBalance: null };
return { tierLabel: null, tierId: null, creditBalance: null };
}
return {
tierLabel: cached.tierLabel,
tierId: cached.tierId,
creditBalance: cached.creditBalance,
};
};
@@ -564,6 +581,7 @@ const scheduleGeminiCliSupplementaryRefresh = (
if (
current.tierLabel === supplementary.tierLabel &&
current.tierId === supplementary.tierId &&
current.creditBalance === supplementary.creditBalance
) {
return prev;
@@ -574,6 +592,7 @@ const scheduleGeminiCliSupplementaryRefresh = (
[fileName]: {
...current,
tierLabel: supplementary.tierLabel,
tierId: supplementary.tierId,
creditBalance: supplementary.creditBalance,
},
};
@@ -591,6 +610,7 @@ const fetchGeminiCliQuota = async (
supplementaryRequestId: number;
buckets: GeminiCliQuotaBucketState[];
tierLabel: string | null;
tierId: string | null;
creditBalance: number | null;
}> => {
const rawAuthIndex = file['auth_index'] ?? file.authIndex;
@@ -664,6 +684,7 @@ const fetchGeminiCliQuota = async (
supplementaryRequestId,
buckets: builtBuckets,
tierLabel: supplementarySnapshot.tierLabel,
tierId: supplementarySnapshot.tierId,
creditBalance: supplementarySnapshot.creditBalance,
};
};
@@ -705,6 +726,8 @@ const renderAntigravityItems = (
});
};
const PREMIUM_GEMINI_CLI_TIER_IDS = new Set(['g1-ultra-tier']);
const renderCodexItems = (
quota: CodexQuotaState,
t: TFunction,
@@ -718,6 +741,7 @@ const renderCodexItems = (
const getPlanLabel = (pt?: string | null): string | null => {
const normalized = normalizePlanType(pt);
if (!normalized) return null;
if (normalized === 'pro') return t('codex_quota.plan_pro');
if (normalized === 'plus') return t('codex_quota.plan_plus');
if (normalized === 'team') return t('codex_quota.plan_team');
if (normalized === 'free') return t('codex_quota.plan_free');
@@ -725,15 +749,17 @@ const renderCodexItems = (
};
const planLabel = getPlanLabel(planType);
const isPremiumPlan = normalizePlanType(planType) === 'pro';
const nodes: ReactNode[] = [];
if (planLabel) {
const valueClass = isPremiumPlan ? styleMap.premiumPlanValue : styleMap.codexPlanValue;
nodes.push(
h(
'div',
{ key: 'plan', className: styleMap.codexPlan },
h('span', { className: styleMap.codexPlanLabel }, t('codex_quota.plan_label')),
h('span', { className: styleMap.codexPlanValue }, planLabel)
h('span', { className: valueClass }, planLabel)
)
);
}
@@ -786,16 +812,19 @@ const renderGeminiCliItems = (
const { createElement: h, Fragment } = React;
const buckets = quota.buckets ?? [];
const tierLabel = quota.tierLabel ?? null;
const tierId = quota.tierId ?? null;
const creditBalance = quota.creditBalance ?? null;
const isPremiumTier = tierId !== null && PREMIUM_GEMINI_CLI_TIER_IDS.has(tierId);
const nodes: ReactNode[] = [];
if (tierLabel) {
const valueClass = isPremiumTier ? styleMap.premiumPlanValue : styleMap.codexPlanValue;
nodes.push(
h(
'div',
{ key: 'tier', className: styleMap.codexPlan },
h('span', { className: styleMap.codexPlanLabel }, t('gemini_cli_quota.tier_label')),
h('span', { className: styleMap.codexPlanValue }, tierLabel)
h('span', { className: valueClass }, tierLabel)
)
);
}
@@ -1148,6 +1177,7 @@ export const GEMINI_CLI_CONFIG: QuotaConfig<
supplementaryRequestId: number;
buckets: GeminiCliQuotaBucketState[];
tierLabel: string | null;
tierId: string | null;
creditBalance: number | null;
}
> = {
@@ -1159,7 +1189,7 @@ export const GEMINI_CLI_CONFIG: QuotaConfig<
fetchQuota: fetchGeminiCliQuota,
storeSelector: (state) => state.geminiCliQuota,
storeSetter: 'setGeminiCliQuota',
buildLoadingState: () => ({ status: 'loading', buckets: [], tierLabel: null, creditBalance: null }),
buildLoadingState: () => ({ status: 'loading', buckets: [], tierLabel: null, tierId: null, creditBalance: null }),
buildSuccessState: (data) => {
const supplementarySnapshot = readGeminiCliSupplementarySnapshot(
data.fileName,
@@ -1170,6 +1200,7 @@ export const GEMINI_CLI_CONFIG: QuotaConfig<
status: 'success',
buckets: data.buckets,
tierLabel: supplementarySnapshot.tierLabel ?? data.tierLabel,
tierId: supplementarySnapshot.tierId ?? data.tierId,
creditBalance: supplementarySnapshot.creditBalance ?? data.creditBalance,
};
},
+4 -1
View File
@@ -639,7 +639,8 @@
"plan_label": "Plan",
"plan_plus": "Plus",
"plan_team": "Team",
"plan_free": "Free"
"plan_free": "Free",
"plan_pro": "Pro"
},
"gemini_cli_quota": {
"title": "Gemini CLI Quota",
@@ -658,6 +659,8 @@
"tier_free": "Free",
"tier_legacy": "Legacy",
"tier_standard": "Standard",
"tier_pro": "Pro",
"tier_ultra": "Ultra",
"credit_label": "Google One AI Credits",
"credit_amount": "{{count}} credits"
},
+4 -1
View File
@@ -642,7 +642,8 @@
"plan_label": "Тариф",
"plan_plus": "Plus",
"plan_team": "Team",
"plan_free": "Free"
"plan_free": "Free",
"plan_pro": "Pro"
},
"gemini_cli_quota": {
"title": "Квота Gemini CLI",
@@ -661,6 +662,8 @@
"tier_free": "Бесплатный",
"tier_legacy": "Устаревший",
"tier_standard": "Стандартный",
"tier_pro": "Pro",
"tier_ultra": "Ultra",
"credit_label": "Google One AI кредиты",
"credit_amount": "{{count}} кредитов"
},
+4 -1
View File
@@ -639,7 +639,8 @@
"plan_label": "套餐",
"plan_plus": "Plus",
"plan_team": "Team",
"plan_free": "Free"
"plan_free": "Free",
"plan_pro": "Pro"
},
"gemini_cli_quota": {
"title": "Gemini CLI 额度",
@@ -658,6 +659,8 @@
"tier_free": "免费版",
"tier_legacy": "旧版",
"tier_standard": "标准版",
"tier_pro": "Pro",
"tier_ultra": "Ultra",
"credit_label": "Google One AI 积分",
"credit_amount": "{{count}} 积分"
},
+39
View File
@@ -512,6 +512,45 @@
text-transform: capitalize;
}
.premiumPlanValue {
display: inline-flex;
align-items: center;
font-weight: 700;
font-size: 12px;
padding: 2px 8px;
border-radius: 999px;
background: linear-gradient(135deg, #fdf3d7, #f0d060);
border: 1px solid #e0b830;
box-shadow: 0 1px 4px rgba(200, 160, 0, 0.18);
color: #7a5c00;
text-transform: capitalize;
@media (dynamic-range: high) {
background: linear-gradient(135deg,
color(display-p3 0.99 0.95 0.82),
color(display-p3 0.97 0.82 0.28));
border-color: color(display-p3 0.90 0.73 0.12);
box-shadow: 0 1px 8px color(display-p3 1.0 0.84 0.0 / 0.25);
color: color(display-p3 0.50 0.38 0.0);
}
}
:global([data-theme='dark']) .premiumPlanValue {
background: linear-gradient(135deg, #3d3210, #5a4a18);
border-color: #8b7030;
box-shadow: 0 1px 8px rgba(180, 140, 0, 0.2);
color: #e8c84c;
@media (dynamic-range: high) {
background: linear-gradient(135deg,
color(display-p3 0.24 0.20 0.06),
color(display-p3 0.38 0.30 0.08));
border-color: color(display-p3 0.58 0.46 0.15);
box-shadow: 0 1px 12px color(display-p3 0.80 0.65 0.0 / 0.2);
color: color(display-p3 0.95 0.82 0.25);
}
}
// 单个认证文件卡片
.fileCard {
background-color: var(--bg-primary);
+39
View File
@@ -318,6 +318,45 @@
text-transform: capitalize;
}
.premiumPlanValue {
display: inline-flex;
align-items: center;
font-weight: 700;
font-size: 12px;
padding: 2px 8px;
border-radius: 999px;
background: linear-gradient(135deg, #fdf3d7, #f0d060);
border: 1px solid #e0b830;
box-shadow: 0 1px 4px rgba(200, 160, 0, 0.18);
color: #7a5c00;
text-transform: capitalize;
@media (dynamic-range: high) {
background: linear-gradient(135deg,
color(display-p3 0.99 0.95 0.82),
color(display-p3 0.97 0.82 0.28));
border-color: color(display-p3 0.90 0.73 0.12);
box-shadow: 0 1px 8px color(display-p3 1.0 0.84 0.0 / 0.25);
color: color(display-p3 0.50 0.38 0.0);
}
}
:global([data-theme='dark']) .premiumPlanValue {
background: linear-gradient(135deg, #3d3210, #5a4a18);
border-color: #8b7030;
box-shadow: 0 1px 8px rgba(180, 140, 0, 0.2);
color: #e8c84c;
@media (dynamic-range: high) {
background: linear-gradient(135deg,
color(display-p3 0.24 0.20 0.06),
color(display-p3 0.38 0.30 0.08));
border-color: color(display-p3 0.58 0.46 0.15);
box-shadow: 0 1px 12px color(display-p3 0.80 0.65 0.0 / 0.2);
color: color(display-p3 0.95 0.82 0.25);
}
}
.fileCard {
background-color: var(--bg-primary);
border: 1px solid var(--border-color);
+1
View File
@@ -223,6 +223,7 @@ export interface GeminiCliQuotaState {
status: 'idle' | 'loading' | 'success' | 'error';
buckets: GeminiCliQuotaBucketState[];
tierLabel?: string | null;
tierId?: string | null;
creditBalance?: number | null;
error?: string;
errorStatus?: number;