mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 08:17:11 +00:00
fix(agy): edge case handling for quota failover
- Fix formatQuotaBar crash on percentage > 100 or < 0 (clamp to 0-100) - Fix shared project accounts excluded from failover (same GCP project = pooled quota) - Fix division by zero in avgQuota when models array empty - Fix null account label fallback to 'Unknown Account'
This commit is contained in:
@@ -625,6 +625,10 @@ export async function findAvailableAccount(
|
||||
): Promise<{ account: AccountInfo; quota: QuotaResult } | null> {
|
||||
const allQuotas = await fetchAllProviderQuotas(provider);
|
||||
|
||||
// Get excluded account's project ID to avoid switching to same-project accounts
|
||||
const excludedProjectId = allQuotas.accounts.find((a) => a.account.id === excludeAccountId)?.quota
|
||||
.projectId;
|
||||
|
||||
for (const { account, quota } of allQuotas.accounts) {
|
||||
// Skip excluded account
|
||||
if (excludeAccountId && account.id === excludeAccountId) {
|
||||
@@ -636,6 +640,11 @@ export async function findAvailableAccount(
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip accounts sharing same GCP project (quota is pooled)
|
||||
if (excludedProjectId && quota.projectId === excludedProjectId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if any model has remaining quota (> 5% to avoid edge cases)
|
||||
const hasQuota = quota.models.some((m) => m.percentage > 5);
|
||||
if (hasQuota) {
|
||||
|
||||
@@ -609,7 +609,7 @@ async function handleDoctor(): Promise<void> {
|
||||
|
||||
// Display per-account quota status
|
||||
for (const { account, quota } of quotaResult.accounts) {
|
||||
const accountLabel = account.email || account.id;
|
||||
const accountLabel = account.email || account.id || 'Unknown Account';
|
||||
const defaultBadge = account.isDefault ? color(' (default)', 'info') : '';
|
||||
|
||||
if (!quota.success) {
|
||||
@@ -624,8 +624,11 @@ async function handleDoctor(): Promise<void> {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate overall quota health
|
||||
const avgQuota = quota.models.reduce((sum, m) => sum + m.percentage, 0) / quota.models.length;
|
||||
// Calculate overall quota health (guard against empty models array)
|
||||
const avgQuota =
|
||||
quota.models.length > 0
|
||||
? quota.models.reduce((sum, m) => sum + m.percentage, 0) / quota.models.length
|
||||
: 0;
|
||||
const statusIcon = avgQuota > 50 ? ok('') : avgQuota > 10 ? warn('') : fail('');
|
||||
|
||||
console.log(` ${statusIcon}${accountLabel}${defaultBadge}`);
|
||||
@@ -681,9 +684,10 @@ async function handleDoctor(): Promise<void> {
|
||||
|
||||
function formatQuotaBar(percentage: number): string {
|
||||
const width = 20;
|
||||
const filled = Math.round((percentage / 100) * width);
|
||||
const clampedPct = Math.max(0, Math.min(100, percentage));
|
||||
const filled = Math.round((clampedPct / 100) * width);
|
||||
const empty = width - filled;
|
||||
const filledChar = percentage > 50 ? '█' : percentage > 10 ? '▓' : '░';
|
||||
const filledChar = clampedPct > 50 ? '█' : clampedPct > 10 ? '▓' : '░';
|
||||
return `[${filledChar.repeat(filled)}${' '.repeat(empty)}]`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user