gravityyy-proxyyy / src /bootstrap /env-accounts.js
bardd's picture
Fix gemini-3.1-pro-high by routing to pro-low with thinkingLevel high.
4badc3b
Raw
History Blame Contribute Delete
5.08 kB
/**
* Bootstrap Antigravity OAuth accounts from environment variables.
*/
import { parseRefreshParts, formatRefreshParts } from '../auth/oauth.js';
import { loadAccounts, saveAccounts } from '../account-manager/storage.js';
import { logger } from '../utils/logger.js';
function envValue(env, key) {
const value = env[key];
return typeof value === 'string' ? value.trim() : '';
}
function isTruthy(value) {
return ['1', 'true', 'yes', 'on'].includes(String(value || '').trim().toLowerCase());
}
function normalizeTier(value) {
const tier = String(value || '').trim().toLowerCase();
if (tier.includes('ultra')) return 'ultra';
if (tier.includes('pro') || tier.includes('premium') || tier.includes('standard')) return 'pro';
if (tier.includes('free')) return 'free';
return 'unknown';
}
function findCredentialIndexes(env) {
const indexes = new Set();
for (const key of Object.keys(env)) {
const match = key.match(/^ANTIGRAVITY_(\d+)_REFRESH_TOKEN$/);
if (match && envValue(env, key)) indexes.add(Number(match[1]));
}
if (indexes.size === 0 && envValue(env, 'ANTIGRAVITY_REFRESH_TOKEN')) {
indexes.add(0);
}
return [...indexes].sort((a, b) => a - b);
}
export function collectEnvAccounts(env = process.env) {
const accounts = [];
for (const index of findCredentialIndexes(env)) {
const prefix = index === 0 ? 'ANTIGRAVITY' : `ANTIGRAVITY_${index}`;
const email = envValue(env, `${prefix}_EMAIL`);
const rawRefreshToken = envValue(env, `${prefix}_REFRESH_TOKEN`);
const projectId = envValue(env, `${prefix}_PROJECT_ID`);
const tier = normalizeTier(envValue(env, `${prefix}_TIER`));
if (!email) {
throw new Error(`${prefix}_EMAIL is required when ${prefix}_REFRESH_TOKEN is set`);
}
if (!rawRefreshToken) continue;
const existingParts = parseRefreshParts(rawRefreshToken);
const resolvedProjectId = projectId
|| existingParts.managedProjectId
|| existingParts.projectId;
const refreshToken = formatRefreshParts({
refreshToken: existingParts.refreshToken,
projectId: existingParts.projectId || resolvedProjectId,
managedProjectId: existingParts.managedProjectId || resolvedProjectId
});
accounts.push({
email,
source: 'oauth',
enabled: true,
refreshToken,
projectId: resolvedProjectId || undefined,
addedAt: new Date().toISOString(),
isInvalid: false,
invalidReason: null,
verifyUrl: null,
modelRateLimits: {},
lastUsed: null,
subscription: {
tier,
projectId: resolvedProjectId || null,
detectedAt: tier !== 'unknown' || resolvedProjectId ? Date.now() : null
},
quota: {
models: {},
lastChecked: null
},
modelQuotaThresholds: {}
});
}
return accounts;
}
export async function bootstrapEnvAccounts(configPath, env = process.env) {
const envAccounts = collectEnvAccounts(env);
if (envAccounts.length === 0) {
return { changed: false, count: 0 };
}
const force = isTruthy(env.FORCE_ENV_ACCOUNTS);
const { accounts: existingAccounts, settings, activeIndex } = await loadAccounts(configPath);
const merged = force ? [] : [...existingAccounts];
for (const envAccount of envAccounts) {
const existingIndex = merged.findIndex(account => account.email === envAccount.email);
if (existingIndex === -1) {
merged.push(envAccount);
} else {
merged[existingIndex] = {
...merged[existingIndex],
...envAccount,
addedAt: merged[existingIndex].addedAt || envAccount.addedAt,
modelRateLimits: force ? {} : (merged[existingIndex].modelRateLimits || {}),
lastUsed: force ? null : (merged[existingIndex].lastUsed || null),
quota: force ? envAccount.quota : (merged[existingIndex].quota || envAccount.quota)
};
}
}
await saveAccounts(configPath, merged, settings, Math.min(activeIndex, Math.max(0, merged.length - 1)));
// saveAccounts logs and swallows I/O errors, so verify persistence explicitly.
const { accounts: persistedAccounts } = await loadAccounts(configPath);
const persistedEmails = new Set(persistedAccounts.map(account => account.email));
const missingEmails = envAccounts
.map(account => account.email)
.filter(email => !persistedEmails.has(email));
if (missingEmails.length > 0) {
throw new Error(`Failed to persist environment accounts: ${missingEmails.join(', ')}`);
}
logger.info(`[Bootstrap] Loaded ${envAccounts.length} Antigravity account(s) from environment${force ? ' (authoritative)' : ''}`);
return { changed: true, count: envAccounts.length };
}