antigravity-usage 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -1
- package/dist/index.js +152 -57
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/core/logger.ts","../src/google/oauth.ts","../src/accounts/types.ts","../src/accounts/storage.ts","../src/core/env.ts","../src/accounts/config.ts","../src/accounts/cache.ts","../src/accounts/manager.ts","../src/google/storage.ts","../src/core/errors.ts","../src/google/token-manager.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/core/mask.ts","../src/commands/status.ts","../src/google/cloudcode.ts","../src/google/parser.ts","../src/local/process-detector.ts","../src/local/port-detective.ts","../src/local/port-prober.ts","../src/local/connect-client.ts","../src/local/local-parser.ts","../src/quota/service.ts","../src/quota/format.ts","../src/render/table.ts","../src/commands/quota.ts","../src/commands/doctor.ts","../src/commands/accounts.ts","../src/commands/wakeup.ts","../src/wakeup/types.ts","../src/wakeup/storage.ts","../src/wakeup/account-resolver.ts","../src/wakeup/schedule-converter.ts","../src/wakeup/cron-installer.ts","../src/wakeup/trigger-service.ts","../src/wakeup/reset-detector.ts"],"sourcesContent":["/**\n * antigravity-usage CLI entry point\n */\n\nimport { Command } from 'commander'\nimport { version } from './version'\nimport { setDebugMode } from './core/logger.js'\n\n// Import commands\nimport { loginCommand } from './commands/login.js'\nimport { logoutCommand } from './commands/logout.js'\nimport { statusCommand } from './commands/status.js'\nimport { quotaCommand } from './commands/quota.js'\nimport { doctorCommand } from './commands/doctor.js'\nimport { accountsCommand } from './commands/accounts.js'\n\nconst program = new Command()\n\nprogram\n .name('antigravity-usage')\n .description('CLI tool to check Antigravity model quota via Google Cloud Code API')\n .version(version)\n .option('--debug', 'Enable debug mode')\n .hook('preAction', (thisCommand) => {\n const opts = thisCommand.opts()\n if (opts.debug) {\n setDebugMode(true)\n }\n })\n\n// Login command\nprogram\n .command('login')\n .description('Authenticate with Google (adds a new account)')\n .option('--no-browser', 'Do not open browser, print URL instead')\n .option('--manual', 'Manual login flow (copy-paste URL)')\n .option('-p, --port <port>', 'Port for OAuth callback server', parseInt)\n .action(loginCommand)\n\n// Logout command\nprogram\n .command('logout [email]')\n .description('Remove stored credentials')\n .option('--all', 'Logout from all accounts')\n .action((email, options) => logoutCommand(options, email))\n\n// Status command\nprogram\n .command('status')\n .description('Show current authentication status')\n .option('--all', 'Show status for all accounts')\n .option('-a, --account <email>', 'Show status for specific account')\n .action(statusCommand)\n\n// Quota command (default)\nprogram\n .command('quota', { isDefault: true })\n .description('Fetch and display quota information')\n .option('--json', 'Output as JSON')\n .option('-m, --method <method>', 'Method to use: auto (default), local, or google', 'auto')\n .option('--all', 'Show quota for all accounts')\n .option('-a, --account <email>', 'Show quota for specific account')\n .option('--refresh', 'Force refresh (ignore cache)')\n .option('--all-models', 'Include autocomplete models (Gemini 2.5) in quota display')\n .action(quotaCommand)\n\n// Accounts command with subcommands\nconst accountsCmd = program\n .command('accounts')\n .description('Manage multiple accounts')\n\naccountsCmd\n .command('list')\n .description('List all accounts')\n .option('--refresh', 'Show refresh tip')\n .action((options) => accountsCommand('list', [], options))\n\naccountsCmd\n .command('add')\n .description('Add a new account (triggers OAuth login)')\n .action(() => accountsCommand('add', [], {}))\n\naccountsCmd\n .command('switch <email>')\n .description('Switch to a different account')\n .action((email) => accountsCommand('switch', [email], {}))\n\naccountsCmd\n .command('remove <email>')\n .description('Remove an account')\n .option('--force', 'Skip confirmation')\n .action((email, options) => accountsCommand('remove', [email], options))\n\naccountsCmd\n .command('current')\n .description('Show current active account')\n .action(() => accountsCommand('current', [], {}))\n\naccountsCmd\n .command('refresh [email]')\n .description('Refresh account tokens')\n .option('--all', 'Refresh all accounts')\n .action((email, options) => accountsCommand('refresh', email ? [email] : [], options))\n\n// Default action for accounts command (show list)\naccountsCmd.action(() => accountsCommand('list', [], {}))\n\n// Doctor command\nprogram\n .command('doctor')\n .description('Run diagnostics and show configuration')\n .action(doctorCommand)\n\n// Wakeup command with subcommands\nimport { wakeupCommand } from './commands/wakeup.js'\n\nconst wakeupCmd = program\n .command('wakeup')\n .description('Auto wake-up and warm up AI models')\n\nwakeupCmd\n .command('config')\n .description('Configure auto wake-up schedule')\n .action(() => wakeupCommand('config', [], {}))\n\nwakeupCmd\n .command('trigger')\n .description('Execute one trigger cycle (called by cron)')\n .option('--scheduled', 'Mark as scheduled trigger')\n .action((options) => wakeupCommand('trigger', [], options))\n\nwakeupCmd\n .command('install')\n .description('Install wake-up schedule to system cron')\n .action(() => wakeupCommand('install', [], {}))\n\nwakeupCmd\n .command('uninstall')\n .description('Remove wake-up schedule from system cron')\n .action(() => wakeupCommand('uninstall', [], {}))\n\nwakeupCmd\n .command('test')\n .description('Test trigger manually')\n .action(() => wakeupCommand('test', [], {}))\n\nwakeupCmd\n .command('history')\n .description('View trigger history')\n .option('--limit <n>', 'Number of records to show', '10')\n .option('--json', 'Output as JSON')\n .action((options) => wakeupCommand('history', [], options))\n\nwakeupCmd\n .command('status')\n .description('Show wake-up status and configuration')\n .action(() => wakeupCommand('status', [], {}))\n\n// Default action for wakeup command (show status)\nwakeupCmd.action(() => wakeupCommand('status', [], {}))\n\n// Parse and run\nprogram.parse()\n\n","/**\n * Version info - imported from package.json\n */\nimport { readFileSync } from 'fs'\nimport { join, dirname } from 'path'\nimport { fileURLToPath } from 'url'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\n\nconst packageJsonPath = join(__dirname, '../package.json')\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'))\n\nexport const version = packageJson.version as string\n","/**\n * Logger utility with debug mode support\n */\n\nlet debugMode = false\n\nexport function setDebugMode(enabled: boolean): void {\n debugMode = enabled\n}\n\nexport function isDebugMode(): boolean {\n return debugMode\n}\n\nexport function debug(category: string, message: string, data?: unknown): void {\n if (!debugMode) return\n \n const timestamp = new Date().toISOString()\n const prefix = `[${timestamp}] [${category}]`\n \n if (data !== undefined) {\n console.error(`${prefix} ${message}`, data)\n } else {\n console.error(`${prefix} ${message}`)\n }\n}\n\nexport function info(message: string): void {\n console.log(message)\n}\n\nexport function warn(message: string): void {\n console.warn(`⚠️ ${message}`)\n}\n\nexport function error(message: string): void {\n console.error(`❌ ${message}`)\n}\n\nexport function success(message: string): void {\n console.log(`✅ ${message}`)\n}\n","/**\n * OAuth configuration and flow\n */\n\nimport { createServer, type IncomingMessage, type ServerResponse } from 'node:http'\nimport { URL, URLSearchParams } from 'node:url'\nimport open from 'open'\nimport inquirer from 'inquirer'\nimport { debug, info, error as logError } from '../core/logger.js'\nimport { getAccountManager } from '../accounts/index.js'\nimport type { OAuthTokenResponse, StoredTokens } from '../quota/types.js'\n\n// OAuth configuration\n// Default credentials provided - users can override with environment variables if needed\nconst OAUTH_CONFIG = {\n clientId: process.env.ANTIGRAVITY_OAUTH_CLIENT_ID || '1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com',\n clientSecret: process.env.ANTIGRAVITY_OAUTH_CLIENT_SECRET || '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',\n authUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n scopes: [\n 'https://www.googleapis.com/auth/cloud-platform',\n 'https://www.googleapis.com/auth/userinfo.email'\n ]\n}\n\n// Cloud Code API configuration\nconst CLOUDCODE_CONFIG = {\n baseUrl: 'https://cloudcode-pa.googleapis.com',\n userAgent: 'antigravity',\n metadata: {\n ideType: 'ANTIGRAVITY',\n platform: 'PLATFORM_UNSPECIFIED',\n pluginType: 'GEMINI'\n },\n onboardAttempts: 5,\n onboardDelayMs: 2000\n}\n\ninterface OAuthOptions {\n noBrowser?: boolean\n port?: number\n manual?: boolean\n}\n\ninterface OAuthResult {\n success: boolean\n email?: string\n error?: string\n}\n\n/**\n * Response types for Cloud Code API\n */\ninterface LoadCodeAssistResponse {\n cloudaicompanionProject?: string | { id?: string }\n paidTier?: { id?: string }\n currentTier?: { id?: string }\n allowedTiers?: Array<{ id?: string; isDefault?: boolean }>\n}\n\ninterface OnboardUserResponse {\n done?: boolean\n response?: {\n cloudaicompanionProject?: string | { id?: string }\n }\n}\n\ninterface ProjectIdResult {\n projectId?: string\n tierId?: string\n}\n\n/**\n * Generate a random state parameter for CSRF protection\n */\nfunction generateState(): string {\n return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)\n}\n\n/**\n * Get available port for callback server\n */\nasync function getAvailablePort(preferredPort?: number): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = createServer()\n server.listen(preferredPort || 0, '127.0.0.1', () => {\n const address = server.address()\n if (address && typeof address === 'object') {\n const port = address.port\n server.close(() => resolve(port))\n } else {\n reject(new Error('Failed to get server address'))\n }\n })\n server.on('error', reject)\n })\n}\n\n/**\n * Exchange authorization code for tokens\n */\nasync function exchangeCodeForTokens(code: string, redirectUri: string): Promise<OAuthTokenResponse> {\n debug('oauth', 'Exchanging code for tokens')\n \n const params = new URLSearchParams({\n code,\n client_id: OAUTH_CONFIG.clientId,\n client_secret: OAUTH_CONFIG.clientSecret,\n redirect_uri: redirectUri,\n grant_type: 'authorization_code'\n })\n \n const response = await fetch(OAUTH_CONFIG.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded'\n },\n body: params.toString()\n })\n \n if (!response.ok) {\n const error = await response.text()\n debug('oauth', 'Token exchange failed', error)\n throw new Error(`Token exchange failed: ${response.status} ${error}`)\n }\n \n const data = await response.json() as OAuthTokenResponse\n debug('oauth', 'Token exchange successful')\n return data\n}\n\n/**\n * Get user email from access token\n */\nasync function getUserEmail(accessToken: string): Promise<string | undefined> {\n debug('oauth', 'Fetching user info')\n \n try {\n const response = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {\n headers: {\n Authorization: `Bearer ${accessToken}`\n }\n })\n \n if (response.ok) {\n const data = await response.json() as { email?: string }\n return data.email\n }\n } catch (err) {\n debug('oauth', 'Failed to get user info', err)\n }\n \n return undefined\n}\n\n/**\n * Extract project ID from cloudaicompanionProject field\n * Handles both string and object { id: string } formats\n */\nexport function extractProjectId(value: unknown): string | undefined {\n // Case 1: Non-empty string\n if (typeof value === 'string' && value.length > 0) {\n return value\n }\n \n // Case 2: Object with 'id' property that is a non-empty string\n if (value && typeof value === 'object' && 'id' in value) {\n const id = (value as { id?: unknown }).id\n if (typeof id === 'string' && id.length > 0) {\n return id\n }\n }\n \n // Case 3: Missing or invalid\n return undefined\n}\n\n/**\n * Pick the tier ID to use for onboarding\n * Priority: default tier from allowedTiers > first tier from allowedTiers > 'LEGACY' > tierIdFromLoad\n */\nexport function pickOnboardTier(\n allowedTiers: Array<{ id?: string; isDefault?: boolean }> | undefined,\n tierIdFromLoad?: string\n): string | undefined {\n if (!allowedTiers || allowedTiers.length === 0) {\n return tierIdFromLoad\n }\n \n // Find default tier\n const defaultTier = allowedTiers.find(t => t.isDefault === true && t.id && t.id.length > 0)\n if (defaultTier?.id) {\n return defaultTier.id\n }\n \n // Find first tier with valid ID\n const firstTier = allowedTiers.find(t => t.id && t.id.length > 0)\n if (firstTier?.id) {\n return firstTier.id\n }\n \n // If tiers exist but have no IDs, use LEGACY\n if (allowedTiers.length > 0) {\n return 'LEGACY'\n }\n \n return tierIdFromLoad\n}\n\n/**\n * Sleep helper for retry delays\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\n/**\n * Try to onboard user with retry logic\n * Calls onboardUser endpoint until done=true or max attempts reached\n */\nasync function tryOnboardUser(accessToken: string, tierId: string): Promise<string | undefined> {\n debug('oauth', `Starting onboard flow with tierId: ${tierId}`)\n \n const payload = {\n tierId,\n metadata: CLOUDCODE_CONFIG.metadata\n }\n \n for (let attempt = 1; attempt <= CLOUDCODE_CONFIG.onboardAttempts; attempt++) {\n debug('oauth', `Onboard attempt ${attempt}/${CLOUDCODE_CONFIG.onboardAttempts}`)\n \n try {\n const response = await fetch(`${CLOUDCODE_CONFIG.baseUrl}/v1internal:onboardUser`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n 'User-Agent': CLOUDCODE_CONFIG.userAgent\n },\n body: JSON.stringify(payload)\n })\n \n if (!response.ok) {\n debug('oauth', `Onboard request failed: ${response.status}`)\n // Don't retry on 403/401 - these are permanent failures\n if (response.status === 401 || response.status === 403) {\n debug('oauth', 'Onboarding forbidden or unauthorized, stopping retries')\n return undefined\n }\n } else {\n const data = await response.json() as OnboardUserResponse\n debug('oauth', `Onboard response: done=${data.done}`)\n \n if (data.done === true) {\n const projectId = extractProjectId(data.response?.cloudaicompanionProject)\n if (projectId) {\n debug('oauth', `Onboarding complete, projectId: ${projectId}`)\n return projectId\n }\n debug('oauth', 'Onboarding done but no projectId in response')\n return undefined\n }\n }\n } catch (err) {\n debug('oauth', `Onboard attempt ${attempt} error:`, err)\n }\n \n // Wait before next attempt (unless this is the last attempt)\n if (attempt < CLOUDCODE_CONFIG.onboardAttempts) {\n debug('oauth', `Waiting ${CLOUDCODE_CONFIG.onboardDelayMs}ms before next attempt`)\n await sleep(CLOUDCODE_CONFIG.onboardDelayMs)\n }\n }\n \n debug('oauth', 'Onboarding attempts exhausted')\n return undefined\n}\n\n/**\n * Resolve project ID from Cloud Code API\n * First tries loadCodeAssist, if no projectId then initiates onboarding\n */\nexport async function resolveProjectId(accessToken: string): Promise<ProjectIdResult> {\n debug('oauth', 'Resolving project ID from Cloud Code API')\n \n try {\n // Step 1: Call loadCodeAssist\n const response = await fetch(`${CLOUDCODE_CONFIG.baseUrl}/v1internal:loadCodeAssist`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n 'User-Agent': CLOUDCODE_CONFIG.userAgent\n },\n body: JSON.stringify({ metadata: CLOUDCODE_CONFIG.metadata })\n })\n \n if (!response.ok) {\n debug('oauth', `loadCodeAssist failed: ${response.status}`)\n return { projectId: undefined, tierId: undefined }\n }\n \n const data = await response.json() as LoadCodeAssistResponse\n \n // Step 2: Extract project ID and tier\n const projectId = extractProjectId(data.cloudaicompanionProject)\n const tierId = data.paidTier?.id || data.currentTier?.id\n \n // Step 3: If we have projectId, return immediately\n if (projectId) {\n debug('oauth', `Got projectId from loadCodeAssist: ${projectId}`)\n return { projectId, tierId }\n }\n \n // Step 4: No projectId - need to onboard\n debug('oauth', 'No projectId in loadCodeAssist response, initiating onboarding')\n \n const onboardTier = pickOnboardTier(data.allowedTiers, tierId)\n \n if (!onboardTier) {\n debug('oauth', 'Cannot determine tier for onboarding')\n return { projectId: undefined, tierId }\n }\n \n // Step 5: Try onboarding\n const onboardedProjectId = await tryOnboardUser(accessToken, onboardTier)\n \n return {\n projectId: onboardedProjectId,\n tierId: onboardTier\n }\n } catch (err) {\n debug('oauth', 'Error resolving project ID', err)\n return { projectId: undefined, tierId: undefined }\n }\n}\n\n/**\n * Complete login process: exchange code for tokens, get user info, resolve project ID\n */\nasync function completeLogin(code: string, redirectUri: string): Promise<OAuthResult> {\n // Exchange code for tokens\n const tokenResponse = await exchangeCodeForTokens(code, redirectUri)\n \n // Get user email\n const email = await getUserEmail(tokenResponse.access_token)\n \n // Resolve project ID from Cloud Code API (may trigger onboarding if needed)\n let projectId: string | undefined\n try {\n const projectResult = await resolveProjectId(tokenResponse.access_token)\n projectId = projectResult.projectId\n if (projectId) {\n debug('oauth', `Project ID resolved: ${projectId}`)\n } else {\n debug('oauth', 'No project ID obtained (will fetch on demand)')\n }\n } catch (err) {\n debug('oauth', 'Failed to resolve project ID during login (will fetch on demand)', err)\n // Continue without project ID - it will be fetched on demand\n }\n \n // Save tokens using account manager\n const tokens: StoredTokens = {\n accessToken: tokenResponse.access_token,\n refreshToken: tokenResponse.refresh_token || '',\n expiresAt: Date.now() + tokenResponse.expires_in * 1000,\n email,\n projectId\n }\n \n // Add/update account via account manager\n if (email) {\n getAccountManager().addAccount(tokens, email)\n }\n \n return { success: true, email }\n}\n\n/**\n * Start OAuth login flow\n */\nexport async function startOAuthFlow(options: OAuthOptions = {}): Promise<OAuthResult> {\n const port = await getAvailablePort(options.port)\n const redirectUri = `http://127.0.0.1:${port}/callback`\n const state = generateState()\n \n debug('oauth', `Starting OAuth flow on port ${port}`)\n \n // Build authorization URL\n const authParams = new URLSearchParams({\n client_id: OAUTH_CONFIG.clientId,\n redirect_uri: redirectUri,\n response_type: 'code',\n scope: OAUTH_CONFIG.scopes.join(' '),\n access_type: 'offline',\n prompt: 'consent',\n state\n })\n \n const authUrl = `${OAUTH_CONFIG.authUrl}?${authParams.toString()}`\n\n // Manual flow check\n if (options.manual) {\n info('')\n info('MANUAL LOGIN MODE')\n info('1. Copy this URL and open it in your browser:')\n info(authUrl)\n info('')\n info('2. Login with your Google account.')\n info('3. You will be redirected to a localhost URL (which may fail to load).')\n info('4. Copy that ENTIRE localhost URL and paste it below.')\n info('')\n \n const { pastedUrl } = await inquirer.prompt([\n {\n type: 'input',\n name: 'pastedUrl',\n message: 'Paste the full redirect URL here:',\n validate: (input: string) => input.trim().length > 0 ? true : 'Please paste the URL'\n }\n ])\n \n try {\n const url = new URL(pastedUrl.trim())\n const code = url.searchParams.get('code')\n const returnedState = url.searchParams.get('state')\n const errorParam = url.searchParams.get('error')\n \n if (errorParam) {\n return { success: false, error: errorParam }\n }\n \n if (!code || returnedState !== state) {\n return { success: false, error: 'Invalid URL: Missing code or state mismatch' }\n }\n \n return await completeLogin(code, redirectUri)\n } catch (err) {\n if (err instanceof Error) {\n return { success: false, error: err.message }\n }\n return { success: false, error: 'Invalid URL format' }\n }\n }\n \n return new Promise((resolve) => {\n let resolved = false\n \n const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n if (resolved) return\n \n const url = new URL(req.url || '/', `http://127.0.0.1:${port}`)\n \n if (url.pathname === '/callback') {\n const code = url.searchParams.get('code')\n const returnedState = url.searchParams.get('state')\n const errorParam = url.searchParams.get('error')\n \n if (errorParam) {\n res.writeHead(400, { 'Content-Type': 'text/html' })\n res.end('<html><body><h1>Login Failed</h1><p>You can close this window.</p></body></html>')\n resolved = true\n server.close()\n resolve({ success: false, error: errorParam })\n return\n }\n \n if (!code || returnedState !== state) {\n res.writeHead(400, { 'Content-Type': 'text/html' })\n res.end('<html><body><h1>Invalid Request</h1><p>State mismatch or missing code.</p></body></html>')\n resolved = true\n server.close()\n resolve({ success: false, error: 'Invalid callback' })\n return\n }\n \n try {\n // Use common login logic\n const result = await completeLogin(code, redirectUri)\n \n res.writeHead(200, { 'Content-Type': 'text/html' })\n res.end(`\n <html>\n <body style=\"font-family: system-ui; padding: 40px; text-align: center;\">\n <h1>Login Successful!</h1>\n <p>You are now logged in${result.email ? ` as <strong>${result.email}</strong>` : ''}.</p>\n <p>You can close this window and return to the terminal.</p>\n </body>\n </html>\n `)\n \n resolved = true\n server.close()\n resolve(result)\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'text/html' })\n res.end('<html><body><h1>Login Failed</h1><p>Token exchange failed.</p></body></html>')\n resolved = true\n server.close()\n resolve({ success: false, error: err instanceof Error ? err.message : 'Unknown error' })\n }\n }\n })\n \n server.listen(port, '127.0.0.1', async () => {\n info('')\n info('Opening browser for Google login...')\n info('')\n \n if (options.noBrowser) {\n info('Open this URL in your browser:')\n info(authUrl)\n } else {\n try {\n await open(authUrl)\n info('If the browser did not open, visit this URL:')\n info(authUrl)\n } catch (err) {\n debug('oauth', 'Failed to open browser', err)\n info('Could not open browser. Please visit this URL:')\n info(authUrl)\n }\n }\n \n info('')\n info('Waiting for authentication...')\n })\n \n // Timeout after 2 minutes\n setTimeout(() => {\n if (!resolved) {\n resolved = true\n server.close()\n resolve({ success: false, error: 'Login timed out' })\n }\n }, 2 * 60 * 1000)\n })\n}\n\n/**\n * Refresh access token using refresh token\n */\nexport async function refreshAccessToken(refreshToken: string): Promise<OAuthTokenResponse> {\n debug('oauth', 'Refreshing access token')\n \n const params = new URLSearchParams({\n refresh_token: refreshToken,\n client_id: OAUTH_CONFIG.clientId,\n client_secret: OAUTH_CONFIG.clientSecret,\n grant_type: 'refresh_token'\n })\n \n const response = await fetch(OAUTH_CONFIG.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded'\n },\n body: params.toString()\n })\n \n if (!response.ok) {\n const error = await response.text()\n debug('oauth', 'Token refresh failed', error)\n throw new Error(`Token refresh failed: ${response.status}`)\n }\n \n const data = await response.json() as OAuthTokenResponse\n debug('oauth', 'Token refresh successful')\n return data\n}\n","/**\n * Type definitions for multi-account support\n */\n\nimport type { StoredTokens, QuotaSnapshot } from '../quota/types.js'\n\n/**\n * Global configuration stored in config.json\n */\nexport interface GlobalConfig {\n version: string\n activeAccount: string | null\n preferences: ConfigPreferences\n}\n\n/**\n * User preferences\n */\nexport interface ConfigPreferences {\n cacheTTL: number // seconds, default 300 (5 minutes)\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG: GlobalConfig = {\n version: '2.0',\n activeAccount: null,\n preferences: {\n cacheTTL: 300\n }\n}\n\n/**\n * Per-account metadata stored in metadata.json\n */\nexport interface AccountMetadata {\n email: string\n addedAt: string // ISO date string\n lastUsed: string // ISO date string\n}\n\n/**\n * Cached quota data stored in cache.json\n */\nexport interface CachedQuota {\n cachedAt: string // ISO date string\n ttl: number // seconds\n data: QuotaSnapshot | null\n}\n\n/**\n * Account info returned by account manager\n */\nexport interface AccountInfo {\n email: string\n isActive: boolean\n metadata: AccountMetadata | null\n tokens: StoredTokens | null\n cache: CachedQuota | null\n status: AccountStatus\n}\n\n/**\n * Account status for display\n */\nexport type AccountStatus = 'valid' | 'expired' | 'invalid'\n\n/**\n * Account summary for list display\n */\nexport interface AccountSummary {\n email: string\n isActive: boolean\n status: AccountStatus\n lastUsed: string | null\n cachedCredits?: {\n used: number\n limit: number\n } | null\n}\n","/**\n * Account storage - file-based operations for multi-account\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, rmSync } from 'node:fs'\nimport { join, basename } from 'node:path'\nimport { getAccountsDir, getAccountDir } from '../core/env.js'\nimport { debug } from '../core/logger.js'\nimport type { StoredTokens } from '../quota/types.js'\nimport type { AccountMetadata, CachedQuota } from './types.js'\n\n/**\n * Ensure accounts directory exists\n */\nexport function ensureAccountsDir(): void {\n const dir = getAccountsDir()\n if (!existsSync(dir)) {\n debug('accounts-storage', `Creating accounts directory: ${dir}`)\n mkdirSync(dir, { recursive: true })\n }\n}\n\n/**\n * Ensure specific account directory exists\n */\nexport function ensureAccountDir(email: string): void {\n ensureAccountsDir()\n const dir = getAccountDir(email)\n if (!existsSync(dir)) {\n debug('accounts-storage', `Creating account directory: ${dir}`)\n mkdirSync(dir, { recursive: true })\n }\n}\n\n/**\n * Check if an account exists\n */\nexport function accountExists(email: string): boolean {\n const dir = getAccountDir(email)\n return existsSync(dir) && existsSync(join(dir, 'tokens.json'))\n}\n\n/**\n * List all account directories (by email)\n */\nexport function listAccountEmails(): string[] {\n const accountsDir = getAccountsDir()\n \n if (!existsSync(accountsDir)) {\n return []\n }\n \n try {\n const entries = readdirSync(accountsDir, { withFileTypes: true })\n const emails: string[] = []\n \n for (const entry of entries) {\n if (entry.isDirectory()) {\n // Check if it has a tokens.json file\n const tokensPath = join(accountsDir, entry.name, 'tokens.json')\n if (existsSync(tokensPath)) {\n emails.push(entry.name)\n }\n }\n }\n \n return emails\n } catch (err) {\n debug('accounts-storage', 'Failed to list accounts', err)\n return []\n }\n}\n\n// ============================================================\n// Token operations\n// ============================================================\n\n/**\n * Save tokens for an account\n */\nexport function saveAccountTokens(email: string, tokens: StoredTokens): void {\n ensureAccountDir(email)\n const path = join(getAccountDir(email), 'tokens.json')\n \n debug('accounts-storage', `Saving tokens for ${email}`)\n writeFileSync(path, JSON.stringify(tokens, null, 2), { mode: 0o600 })\n}\n\n/**\n * Load tokens for an account\n */\nexport function loadAccountTokens(email: string): StoredTokens | null {\n const path = join(getAccountDir(email), 'tokens.json')\n \n if (!existsSync(path)) {\n debug('accounts-storage', `No tokens file for ${email}`)\n return null\n }\n \n try {\n const content = readFileSync(path, 'utf-8')\n return JSON.parse(content) as StoredTokens\n } catch (err) {\n debug('accounts-storage', `Failed to parse tokens for ${email}`, err)\n return null\n }\n}\n\n// ============================================================\n// Metadata operations\n// ============================================================\n\n/**\n * Save metadata for an account\n */\nexport function saveAccountMetadata(email: string, metadata: AccountMetadata): void {\n ensureAccountDir(email)\n const path = join(getAccountDir(email), 'metadata.json')\n \n debug('accounts-storage', `Saving metadata for ${email}`)\n writeFileSync(path, JSON.stringify(metadata, null, 2), { mode: 0o600 })\n}\n\n/**\n * Load metadata for an account\n */\nexport function loadAccountMetadata(email: string): AccountMetadata | null {\n const path = join(getAccountDir(email), 'metadata.json')\n \n if (!existsSync(path)) {\n return null\n }\n \n try {\n const content = readFileSync(path, 'utf-8')\n return JSON.parse(content) as AccountMetadata\n } catch (err) {\n debug('accounts-storage', `Failed to parse metadata for ${email}`, err)\n return null\n }\n}\n\n/**\n * Update lastUsed timestamp for an account\n */\nexport function updateLastUsed(email: string): void {\n const metadata = loadAccountMetadata(email)\n if (metadata) {\n metadata.lastUsed = new Date().toISOString()\n saveAccountMetadata(email, metadata)\n }\n}\n\n// ============================================================\n// Cache operations\n// ============================================================\n\n/**\n * Save cached quota for an account\n */\nexport function saveAccountCache(email: string, cache: CachedQuota): void {\n ensureAccountDir(email)\n const path = join(getAccountDir(email), 'cache.json')\n \n debug('accounts-storage', `Saving cache for ${email}`)\n writeFileSync(path, JSON.stringify(cache, null, 2))\n}\n\n/**\n * Load cached quota for an account\n */\nexport function loadAccountCache(email: string): CachedQuota | null {\n const path = join(getAccountDir(email), 'cache.json')\n \n if (!existsSync(path)) {\n return null\n }\n \n try {\n const content = readFileSync(path, 'utf-8')\n return JSON.parse(content) as CachedQuota\n } catch (err) {\n debug('accounts-storage', `Failed to parse cache for ${email}`, err)\n return null\n }\n}\n\n/**\n * Delete cache for an account\n */\nexport function deleteAccountCache(email: string): void {\n const path = join(getAccountDir(email), 'cache.json')\n \n if (existsSync(path)) {\n try {\n rmSync(path)\n debug('accounts-storage', `Deleted cache for ${email}`)\n } catch (err) {\n debug('accounts-storage', `Failed to delete cache for ${email}`, err)\n }\n }\n}\n\n// ============================================================\n// Account deletion\n// ============================================================\n\n/**\n * Delete an account and all its data\n */\nexport function deleteAccount(email: string): boolean {\n const dir = getAccountDir(email)\n \n if (!existsSync(dir)) {\n debug('accounts-storage', `Account ${email} does not exist`)\n return false\n }\n \n try {\n rmSync(dir, { recursive: true, force: true })\n debug('accounts-storage', `Deleted account ${email}`)\n return true\n } catch (err) {\n debug('accounts-storage', `Failed to delete account ${email}`, err)\n return false\n }\n}\n","/**\n * Environment and platform utilities\n */\n\nimport { homedir, platform } from 'node:os'\nimport { join } from 'node:path'\n\nexport type Platform = 'windows' | 'macos' | 'linux'\n\n/**\n * Get the current platform\n */\nexport function getPlatform(): Platform {\n const p = platform()\n if (p === 'win32') return 'windows'\n if (p === 'darwin') return 'macos'\n return 'linux'\n}\n\n/**\n * Get the config directory for this application\n * - Windows: %APPDATA%/antigravity-usage\n * - macOS: ~/Library/Application Support/antigravity-usage\n * - Linux: ~/.config/antigravity-usage\n */\nexport function getConfigDir(): string {\n const p = getPlatform()\n const home = homedir()\n \n switch (p) {\n case 'windows':\n return join(process.env.APPDATA || join(home, 'AppData', 'Roaming'), 'antigravity-usage')\n case 'macos':\n return join(home, 'Library', 'Application Support', 'antigravity-usage')\n case 'linux':\n default:\n return join(process.env.XDG_CONFIG_HOME || join(home, '.config'), 'antigravity-usage')\n }\n}\n\n/**\n * Get the path to the tokens file (legacy - single account)\n */\nexport function getTokensPath(): string {\n return join(getConfigDir(), 'tokens.json')\n}\n\n/**\n * Get the accounts directory\n */\nexport function getAccountsDir(): string {\n return join(getConfigDir(), 'accounts')\n}\n\n/**\n * Get the directory for a specific account\n * @param email Account email address\n */\nexport function getAccountDir(email: string): string {\n // Sanitize email for filesystem (replace special chars)\n const safeName = email.replace(/[^a-zA-Z0-9@._-]/g, '_')\n return join(getAccountsDir(), safeName)\n}\n\n/**\n * Get the path to global config file\n */\nexport function getGlobalConfigPath(): string {\n return join(getConfigDir(), 'config.json')\n}\n","/**\n * Global configuration management\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { getGlobalConfigPath, getConfigDir } from '../core/env.js'\nimport { debug } from '../core/logger.js'\nimport { DEFAULT_CONFIG, type GlobalConfig } from './types.js'\n\n/**\n * Load global config from disk\n */\nexport function loadConfig(): GlobalConfig {\n const path = getGlobalConfigPath()\n \n if (!existsSync(path)) {\n debug('config', 'No config file found, using defaults')\n return { ...DEFAULT_CONFIG }\n }\n \n try {\n const content = readFileSync(path, 'utf-8')\n const config = JSON.parse(content) as Partial<GlobalConfig>\n \n // Merge with defaults to ensure all fields exist\n return {\n ...DEFAULT_CONFIG,\n ...config,\n preferences: {\n ...DEFAULT_CONFIG.preferences,\n ...config.preferences\n }\n }\n } catch (err) {\n debug('config', 'Failed to parse config, using defaults', err)\n return { ...DEFAULT_CONFIG }\n }\n}\n\n/**\n * Save global config to disk\n */\nexport function saveConfig(config: GlobalConfig): void {\n const path = getGlobalConfigPath()\n const dir = dirname(path)\n \n // Ensure directory exists\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n \n debug('config', `Saving config to ${path}`)\n writeFileSync(path, JSON.stringify(config, null, 2))\n}\n\n/**\n * Get the active account email\n */\nexport function getActiveAccountEmail(): string | null {\n const config = loadConfig()\n return config.activeAccount\n}\n\n/**\n * Set the active account email\n */\nexport function setActiveAccountEmail(email: string | null): void {\n const config = loadConfig()\n config.activeAccount = email\n saveConfig(config)\n}\n\n/**\n * Get cache TTL in seconds\n */\nexport function getCacheTTL(): number {\n const config = loadConfig()\n return config.preferences.cacheTTL\n}\n","/**\n * Cache management for quota data\n */\n\nimport { loadAccountCache, saveAccountCache, deleteAccountCache } from './storage.js'\nimport { getCacheTTL } from './config.js'\nimport { debug } from '../core/logger.js'\nimport type { QuotaSnapshot } from '../quota/types.js'\nimport type { CachedQuota } from './types.js'\n\n/**\n * Check if cache is valid for an account\n */\nexport function isCacheValid(email: string): boolean {\n const cache = loadAccountCache(email)\n \n if (!cache || !cache.data) {\n debug('cache', `No valid cache for ${email}`)\n return false\n }\n \n const cachedAt = new Date(cache.cachedAt).getTime()\n const ttlMs = cache.ttl * 1000\n const now = Date.now()\n \n const isValid = (now - cachedAt) < ttlMs\n debug('cache', `Cache for ${email} is ${isValid ? 'valid' : 'stale'}`)\n \n return isValid\n}\n\n/**\n * Get cache age in seconds\n */\nexport function getCacheAge(email: string): number | null {\n const cache = loadAccountCache(email)\n \n if (!cache) {\n return null\n }\n \n const cachedAt = new Date(cache.cachedAt).getTime()\n return Math.floor((Date.now() - cachedAt) / 1000)\n}\n\n/**\n * Save quota data to cache\n */\nexport function saveCache(email: string, data: QuotaSnapshot): void {\n const ttl = getCacheTTL()\n \n const cache: CachedQuota = {\n cachedAt: new Date().toISOString(),\n ttl,\n data\n }\n \n saveAccountCache(email, cache)\n debug('cache', `Cached quota for ${email}, TTL: ${ttl}s`)\n}\n\n/**\n * Load cached quota data\n */\nexport function loadCache(email: string): QuotaSnapshot | null {\n const cache = loadAccountCache(email)\n return cache?.data || null\n}\n\n/**\n * Load cache with metadata\n */\nexport function loadCacheWithMeta(email: string): CachedQuota | null {\n return loadAccountCache(email)\n}\n\n/**\n * Invalidate cache for an account\n */\nexport function invalidateCache(email: string): void {\n deleteAccountCache(email)\n debug('cache', `Invalidated cache for ${email}`)\n}\n","/**\n * Account manager - orchestrates multi-account operations\n */\n\nimport { debug } from '../core/logger.js'\nimport { \n listAccountEmails, \n loadAccountTokens, \n saveAccountTokens,\n loadAccountMetadata,\n saveAccountMetadata,\n accountExists,\n deleteAccount as deleteAccountDir,\n updateLastUsed\n} from './storage.js'\nimport { \n getActiveAccountEmail, \n setActiveAccountEmail \n} from './config.js'\nimport { \n isCacheValid, \n loadCacheWithMeta,\n getCacheAge\n} from './cache.js'\nimport type { StoredTokens } from '../quota/types.js'\nimport type { \n AccountInfo, \n AccountMetadata, \n AccountStatus, \n AccountSummary \n} from './types.js'\n\n// Refresh token 5 minutes before expiry\nconst EXPIRY_BUFFER_MS = 5 * 60 * 1000\n\n/**\n * Account Manager - singleton class for managing multiple accounts\n */\nexport class AccountManager {\n private static instance: AccountManager | null = null\n \n private constructor() {}\n \n static getInstance(): AccountManager {\n if (!AccountManager.instance) {\n AccountManager.instance = new AccountManager()\n }\n return AccountManager.instance\n }\n \n /**\n * Reset instance (for testing)\n */\n static resetInstance(): void {\n AccountManager.instance = null\n }\n \n /**\n * Get all account emails\n */\n getAccountEmails(): string[] {\n return listAccountEmails()\n }\n \n /**\n * Get active account email\n */\n getActiveEmail(): string | null {\n return getActiveAccountEmail()\n }\n \n /**\n * Set active account\n */\n setActiveAccount(email: string): boolean {\n if (!accountExists(email)) {\n debug('account-manager', `Account ${email} does not exist`)\n return false\n }\n \n setActiveAccountEmail(email)\n updateLastUsed(email)\n debug('account-manager', `Switched to account ${email}`)\n return true\n }\n \n /**\n * Check if an account exists\n */\n hasAccount(email: string): boolean {\n return accountExists(email)\n }\n \n /**\n * Get account status\n */\n getAccountStatus(email: string): AccountStatus {\n const tokens = loadAccountTokens(email)\n \n if (!tokens) {\n return 'invalid'\n }\n \n // Check if token is expired\n const now = Date.now()\n if (now >= tokens.expiresAt - EXPIRY_BUFFER_MS) {\n // Expired, but might have refresh token\n if (tokens.refreshToken) {\n return 'expired' // Can be refreshed\n }\n return 'invalid'\n }\n \n return 'valid'\n }\n \n /**\n * Get detailed account info\n */\n getAccountInfo(email: string): AccountInfo | null {\n if (!accountExists(email)) {\n return null\n }\n \n const activeEmail = getActiveAccountEmail()\n const tokens = loadAccountTokens(email)\n const metadata = loadAccountMetadata(email)\n const cache = loadCacheWithMeta(email)\n const status = this.getAccountStatus(email)\n \n return {\n email,\n isActive: email === activeEmail,\n tokens,\n metadata,\n cache,\n status\n }\n }\n \n /**\n * Get account summaries for list display\n */\n getAccountSummaries(): AccountSummary[] {\n const emails = this.getAccountEmails()\n const activeEmail = getActiveAccountEmail()\n \n return emails.map(email => {\n const metadata = loadAccountMetadata(email)\n const cache = loadCacheWithMeta(email)\n const status = this.getAccountStatus(email)\n \n // Extract credits from cache if available\n let cachedCredits: { used: number; limit: number } | null = null\n if (cache?.data?.promptCredits) {\n const pc = cache.data.promptCredits\n cachedCredits = {\n used: pc.monthly - pc.available,\n limit: pc.monthly\n }\n }\n \n return {\n email,\n isActive: email === activeEmail,\n status,\n lastUsed: metadata?.lastUsed || null,\n cachedCredits\n }\n })\n }\n \n /**\n * Add a new account after successful OAuth\n */\n addAccount(tokens: StoredTokens, email: string): void {\n debug('account-manager', `Adding account ${email}`)\n \n // Save tokens\n saveAccountTokens(email, tokens)\n \n // Create metadata\n const now = new Date().toISOString()\n const metadata: AccountMetadata = {\n email,\n addedAt: now,\n lastUsed: now\n }\n saveAccountMetadata(email, metadata)\n \n // Set as active account\n setActiveAccountEmail(email)\n \n debug('account-manager', `Account ${email} added and set as active`)\n }\n \n /**\n * Update tokens for existing account\n */\n updateTokens(email: string, tokens: StoredTokens): void {\n if (!accountExists(email)) {\n debug('account-manager', `Cannot update tokens: account ${email} does not exist`)\n return\n }\n \n saveAccountTokens(email, tokens)\n updateLastUsed(email)\n debug('account-manager', `Updated tokens for ${email}`)\n }\n \n /**\n * Remove an account\n */\n removeAccount(email: string): boolean {\n if (!accountExists(email)) {\n debug('account-manager', `Account ${email} does not exist`)\n return false\n }\n \n // If removing active account, clear active\n const activeEmail = getActiveAccountEmail()\n if (email === activeEmail) {\n setActiveAccountEmail(null)\n }\n \n const deleted = deleteAccountDir(email)\n \n // If we deleted the active and there are other accounts, set first as active\n if (deleted && email === activeEmail) {\n const remaining = this.getAccountEmails()\n if (remaining.length > 0) {\n setActiveAccountEmail(remaining[0])\n debug('account-manager', `Set ${remaining[0]} as new active account`)\n }\n }\n \n return deleted\n }\n \n /**\n * Remove all accounts\n */\n removeAllAccounts(): number {\n const emails = this.getAccountEmails()\n let count = 0\n \n for (const email of emails) {\n if (deleteAccountDir(email)) {\n count++\n }\n }\n \n setActiveAccountEmail(null)\n debug('account-manager', `Removed ${count} accounts`)\n \n return count\n }\n \n /**\n * Get tokens for an account\n */\n getTokens(email: string): StoredTokens | null {\n return loadAccountTokens(email)\n }\n \n /**\n * Get tokens for active account\n */\n getActiveTokens(): StoredTokens | null {\n const email = getActiveAccountEmail()\n if (!email) {\n return null\n }\n return loadAccountTokens(email)\n }\n \n /**\n * Check if cache is valid for an account\n */\n isCacheValid(email: string): boolean {\n return isCacheValid(email)\n }\n \n /**\n * Get cache age in seconds\n */\n getCacheAge(email: string): number | null {\n return getCacheAge(email)\n }\n}\n\n/**\n * Get account manager instance\n */\nexport function getAccountManager(): AccountManager {\n return AccountManager.getInstance()\n}\n","/**\n * Token storage - file-based implementation\n * \n * This module provides backward-compatible token storage.\n * It routes to the active account in the new multi-account structure.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { getTokensPath, getConfigDir, getAccountDir } from '../core/env.js'\nimport { debug } from '../core/logger.js'\nimport { \n getActiveAccountEmail,\n setActiveAccountEmail\n} from '../accounts/config.js'\nimport {\n saveAccountTokens,\n loadAccountTokens,\n deleteAccount,\n accountExists\n} from '../accounts/storage.js'\nimport type { StoredTokens } from '../quota/types.js'\n\n/**\n * Save tokens to disk\n * Routes to active account in multi-account structure\n */\nexport function saveTokens(tokens: StoredTokens): void {\n const email = tokens.email\n \n if (!email) {\n // Fallback to legacy storage if no email\n const path = getTokensPath()\n const dir = dirname(path)\n \n debug('storage', `Saving tokens to legacy path ${path}`)\n \n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n \n writeFileSync(path, JSON.stringify(tokens, null, 2), { mode: 0o600 })\n return\n }\n \n // Use multi-account storage\n debug('storage', `Saving tokens for account ${email}`)\n saveAccountTokens(email, tokens)\n \n // Set as active if no active account\n if (!getActiveAccountEmail()) {\n setActiveAccountEmail(email)\n }\n}\n\n/**\n * Load tokens from disk\n * First tries active account, then falls back to legacy path\n */\nexport function loadTokens(): StoredTokens | null {\n // Try active account first\n const activeEmail = getActiveAccountEmail()\n \n if (activeEmail) {\n const tokens = loadAccountTokens(activeEmail)\n if (tokens) {\n debug('storage', `Loaded tokens for active account ${activeEmail}`)\n return tokens\n }\n }\n \n // Fallback to legacy path\n const legacyPath = getTokensPath()\n \n debug('storage', `Loading tokens from legacy path ${legacyPath}`)\n \n if (!existsSync(legacyPath)) {\n debug('storage', 'No tokens file found')\n return null\n }\n \n try {\n const content = readFileSync(legacyPath, 'utf-8')\n const tokens = JSON.parse(content) as StoredTokens\n debug('storage', 'Tokens loaded successfully from legacy path')\n return tokens\n } catch (err) {\n debug('storage', 'Failed to parse tokens file', err)\n return null\n }\n}\n\n/**\n * Delete stored tokens\n * Removes active account in multi-account structure\n */\nexport function deleteTokens(): boolean {\n const activeEmail = getActiveAccountEmail()\n \n if (activeEmail && accountExists(activeEmail)) {\n debug('storage', `Deleting account ${activeEmail}`)\n return deleteAccount(activeEmail)\n }\n \n // Fallback to legacy path\n const path = getTokensPath()\n \n debug('storage', `Deleting tokens at legacy path ${path}`)\n \n if (!existsSync(path)) {\n debug('storage', 'No tokens file to delete')\n return false\n }\n \n try {\n unlinkSync(path)\n debug('storage', 'Tokens deleted successfully')\n return true\n } catch (err) {\n debug('storage', 'Failed to delete tokens', err)\n return false\n }\n}\n\n/**\n * Check if tokens exist\n */\nexport function hasTokens(): boolean {\n // Check active account\n const activeEmail = getActiveAccountEmail()\n if (activeEmail && accountExists(activeEmail)) {\n return true\n }\n \n // Fallback to legacy\n return existsSync(getTokensPath())\n}\n\n/**\n * Get config directory info for doctor command\n */\nexport function getStorageInfo(): { configDir: string; tokensPath: string; exists: boolean } {\n const configDir = getConfigDir()\n const activeEmail = getActiveAccountEmail()\n \n // Prefer active account path\n let tokensPath: string\n let exists: boolean\n \n if (activeEmail) {\n tokensPath = `${getAccountDir(activeEmail)}/tokens.json`\n exists = accountExists(activeEmail)\n } else {\n tokensPath = getTokensPath()\n exists = existsSync(tokensPath)\n }\n \n return {\n configDir,\n tokensPath,\n exists\n }\n}\n","/**\n * Custom error classes for antigravity-usage CLI\n */\n\nexport class NotLoggedInError extends Error {\n constructor(message = 'Not logged in. Run: antigravity-usage login') {\n super(message)\n this.name = 'NotLoggedInError'\n }\n}\n\nexport class AuthenticationError extends Error {\n constructor(message = 'Authentication failed. Please login again.') {\n super(message)\n this.name = 'AuthenticationError'\n }\n}\n\nexport class NetworkError extends Error {\n constructor(message = 'Network error. Please check your connection.') {\n super(message)\n this.name = 'NetworkError'\n }\n}\n\nexport class RateLimitError extends Error {\n retryAfterMs?: number\n\n constructor(message = 'Rate limited. Please try again later.', retryAfterMs?: number) {\n super(message)\n this.name = 'RateLimitError'\n this.retryAfterMs = retryAfterMs\n }\n}\n\nexport class APIError extends Error {\n statusCode?: number\n \n constructor(message: string, statusCode?: number) {\n super(message)\n this.name = 'APIError'\n this.statusCode = statusCode\n }\n}\n\nexport class TokenRefreshError extends Error {\n /** Original error that caused the refresh failure */\n cause?: Error\n /** HTTP status code if available */\n statusCode?: number\n /** Whether the error is retryable (network issues) vs permanent (invalid token) */\n isRetryable: boolean\n \n constructor(\n message = 'Failed to refresh token. Please login again.',\n options?: {\n cause?: Error\n statusCode?: number\n isRetryable?: boolean\n }\n ) {\n super(message)\n this.name = 'TokenRefreshError'\n this.cause = options?.cause\n this.statusCode = options?.statusCode\n // Default: retryable unless we get a 400/401 (invalid_grant, etc.)\n this.isRetryable = options?.isRetryable ?? true\n }\n \n /** Get detailed error message including cause */\n getDetailedMessage(): string {\n let msg = this.message\n if (this.statusCode) {\n msg += ` (HTTP ${this.statusCode})`\n }\n if (this.cause) {\n msg += `: ${this.cause.message}`\n }\n return msg\n }\n}\n\nexport class AntigravityNotRunningError extends Error {\n constructor(message = 'Antigravity language server is not running. Please start Antigravity in your IDE.') {\n super(message)\n this.name = 'AntigravityNotRunningError'\n }\n}\n\nexport class LocalConnectionError extends Error {\n constructor(message = 'Failed to connect to local Antigravity server.') {\n super(message)\n this.name = 'LocalConnectionError'\n }\n}\n\nexport class PortDetectionError extends Error {\n constructor(message = 'Could not detect Antigravity server port.') {\n super(message)\n this.name = 'PortDetectionError'\n }\n}\n\nexport class NoAuthMethodAvailableError extends Error {\n constructor(message = 'Unable to fetch quota: Antigravity is not running and you are not logged in.\\n\\nPlease do one of the following:\\n • Run Antigravity in your IDE (VSCode, etc.), or\\n • Login with: antigravity-usage login') {\n super(message)\n this.name = 'NoAuthMethodAvailableError'\n }\n}\n\n","/**\n * Token manager with automatic refresh\n * \n * Updated for multi-account support - can manage tokens for specific accounts\n * or default to the active account.\n */\n\nimport { loadTokens, saveTokens, hasTokens } from './storage.js'\nimport { refreshAccessToken } from './oauth.js'\nimport { debug } from '../core/logger.js'\nimport { NotLoggedInError, TokenRefreshError } from '../core/errors.js'\nimport { \n getActiveAccountEmail,\n loadAccountTokens,\n saveAccountTokens,\n accountExists,\n updateLastUsed\n} from '../accounts/index.js'\nimport type { StoredTokens } from '../quota/types.js'\n\n// Refresh token 5 minutes before expiry\nconst EXPIRY_BUFFER_MS = 5 * 60 * 1000\n\n/**\n * Token manager class for handling authentication\n * Can work with active account or a specific account email\n */\nexport class TokenManager {\n private tokens: StoredTokens | null = null\n private accountEmail: string | null = null\n \n constructor(email?: string) {\n if (email) {\n // Specific account requested\n this.accountEmail = email\n this.tokens = loadAccountTokens(email)\n } else {\n // Use active account\n this.accountEmail = getActiveAccountEmail()\n \n // If we have an active account email, use account-specific storage\n // Otherwise fall back to legacy default storage\n if (this.accountEmail) {\n this.tokens = loadAccountTokens(this.accountEmail)\n } else {\n this.tokens = loadTokens()\n }\n }\n }\n \n /**\n * Get the email this manager is for\n */\n getAccountEmail(): string | null {\n return this.accountEmail || this.tokens?.email || null\n }\n \n /**\n * Check if user is logged in (has tokens)\n */\n isLoggedIn(): boolean {\n if (this.accountEmail) {\n return accountExists(this.accountEmail) && this.tokens !== null\n }\n return hasTokens() && this.tokens !== null\n }\n \n /**\n * Get the stored email\n */\n getEmail(): string | undefined {\n return this.tokens?.email\n }\n \n /**\n * Get token expiry time\n */\n getExpiresAt(): Date | undefined {\n if (!this.tokens) return undefined\n return new Date(this.tokens.expiresAt)\n }\n \n /**\n * Get stored project ID\n */\n getProjectId(): string | undefined {\n return this.tokens?.projectId\n }\n \n /**\n * Set and persist project ID\n */\n setProjectId(projectId: string): void {\n if (!this.tokens) return\n \n this.tokens.projectId = projectId\n \n // Save to disk\n if (this.accountEmail) {\n saveAccountTokens(this.accountEmail, this.tokens)\n } else {\n saveTokens(this.tokens)\n }\n \n debug('token-manager', `Project ID saved: ${projectId}`)\n }\n \n /**\n * Check if token is expired or about to expire\n */\n isTokenExpired(): boolean {\n if (!this.tokens) return true\n return Date.now() >= this.tokens.expiresAt - EXPIRY_BUFFER_MS\n }\n \n /**\n * Get a valid access token, refreshing if necessary\n */\n async getValidAccessToken(): Promise<string> {\n if (!this.tokens) {\n throw new NotLoggedInError()\n }\n \n debug('token-manager', 'Checking token validity')\n \n // Check if token needs refresh\n if (this.isTokenExpired()) {\n debug('token-manager', 'Token expired or expiring soon, refreshing...')\n await this.refreshToken()\n }\n \n return this.tokens.accessToken\n }\n \n /**\n * Refresh the access token with retry logic\n * Retries on transient network errors, fails immediately on permanent errors (invalid_grant)\n */\n async refreshToken(): Promise<void> {\n if (!this.tokens?.refreshToken) {\n throw new NotLoggedInError('No refresh token available. Please login again.')\n }\n \n const MAX_RETRIES = 3\n const BASE_DELAY_MS = 1000 // 1s, 2s, 4s exponential backoff\n \n let lastError: Error | undefined\n \n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n try {\n debug('token-manager', `Refreshing token (attempt ${attempt}/${MAX_RETRIES})...`)\n const response = await refreshAccessToken(this.tokens.refreshToken)\n \n // Update tokens\n this.tokens = {\n accessToken: response.access_token,\n refreshToken: response.refresh_token || this.tokens.refreshToken,\n expiresAt: Date.now() + response.expires_in * 1000,\n email: this.tokens.email,\n projectId: this.tokens.projectId\n }\n \n // Save to disk\n if (this.accountEmail) {\n saveAccountTokens(this.accountEmail, this.tokens)\n updateLastUsed(this.accountEmail)\n } else {\n saveTokens(this.tokens)\n }\n \n debug('token-manager', 'Token refreshed successfully')\n return // Success!\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err))\n \n // Check if this is a permanent error (don't retry)\n const errorMessage = lastError.message.toLowerCase()\n const isPermanentError = \n errorMessage.includes('invalid_grant') ||\n errorMessage.includes('400') ||\n errorMessage.includes('401') ||\n errorMessage.includes('invalid_token') ||\n errorMessage.includes('token has been revoked')\n \n if (isPermanentError) {\n debug('token-manager', `Token refresh failed permanently: ${lastError.message}`)\n throw new TokenRefreshError(\n `Refresh token invalid or expired. Please login again.`,\n { cause: lastError, isRetryable: false }\n )\n }\n \n // Transient error - retry with exponential backoff\n if (attempt < MAX_RETRIES) {\n const delayMs = BASE_DELAY_MS * Math.pow(2, attempt - 1)\n debug('token-manager', `Token refresh attempt ${attempt} failed: ${lastError.message}. Retrying in ${delayMs}ms...`)\n await this.sleep(delayMs)\n } else {\n debug('token-manager', `Token refresh failed after ${MAX_RETRIES} attempts: ${lastError.message}`)\n }\n }\n }\n \n // All retries exhausted\n throw new TokenRefreshError(\n `Failed to refresh token after ${MAX_RETRIES} attempts`,\n { cause: lastError, isRetryable: true }\n )\n }\n \n /**\n * Sleep helper for retry delays\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n }\n \n /**\n * Reload tokens from disk\n */\n reload(): void {\n if (this.accountEmail) {\n this.tokens = loadAccountTokens(this.accountEmail)\n } else {\n this.tokens = loadTokens()\n }\n }\n}\n\n// Singleton instance for default (active account) manager\nlet tokenManagerInstance: TokenManager | null = null\n\n/**\n * Get the token manager instance for active account\n */\nexport function getTokenManager(): TokenManager {\n if (!tokenManagerInstance) {\n tokenManagerInstance = new TokenManager()\n }\n return tokenManagerInstance\n}\n\n/**\n * Get token manager for a specific account\n */\nexport function getTokenManagerForAccount(email: string): TokenManager {\n return new TokenManager(email)\n}\n\n/**\n * Reset the token manager (for testing or after account changes)\n */\nexport function resetTokenManager(): void {\n tokenManagerInstance = null\n}\n","/**\n * Login command - authenticate with Google\n * \n * This is kept for backward compatibility.\n * For multi-account management, use `antigravity-usage accounts add`\n */\n\nimport { startOAuthFlow } from '../google/oauth.js'\nimport { getAccountManager } from '../accounts/index.js'\nimport { success, error as logError, info } from '../core/logger.js'\nimport { resetTokenManager } from '../google/token-manager.js'\n\ninterface LoginOptions {\n noBrowser?: boolean\n port?: number\n manual?: boolean\n}\n\nexport async function loginCommand(options: LoginOptions): Promise<void> {\n const manager = getAccountManager()\n const existingAccounts = manager.getAccountEmails()\n \n if (existingAccounts.length > 0) {\n info(`You have ${existingAccounts.length} account(s). Adding another account...`)\n }\n \n const result = await startOAuthFlow({\n noBrowser: options.noBrowser,\n port: options.port,\n manual: options.manual\n })\n \n if (result.success) {\n // Reset token manager to pick up new active account\n resetTokenManager()\n \n success(`Logged in successfully${result.email ? ` as ${result.email}` : ''}!`)\n \n const accounts = manager.getAccountEmails()\n if (accounts.length > 1) {\n info(`\\nYou now have ${accounts.length} accounts. Use \\`antigravity-usage accounts list\\` to see all.`)\n }\n \n process.exit(0)\n } else {\n logError(`Login failed: ${result.error}`)\n process.exit(1)\n }\n}\n","/**\n * Logout command - remove account(s)\n */\n\nimport { getAccountManager } from '../accounts/index.js'\nimport { resetTokenManager } from '../google/token-manager.js'\nimport { success, warn, info } from '../core/logger.js'\n\ninterface LogoutOptions {\n all?: boolean\n}\n\nexport function logoutCommand(options: LogoutOptions, email?: string): void {\n const manager = getAccountManager()\n \n // Logout all accounts\n if (options.all) {\n const count = manager.removeAllAccounts()\n resetTokenManager()\n \n if (count > 0) {\n success(`Logged out of ${count} account(s).`)\n } else {\n warn('No accounts to log out.')\n }\n return\n }\n \n // Logout specific account\n if (email) {\n if (!manager.hasAccount(email)) {\n warn(`Account '${email}' not found.`)\n return\n }\n \n const removed = manager.removeAccount(email)\n resetTokenManager()\n \n if (removed) {\n success(`Logged out of ${email}.`)\n \n const remaining = manager.getAccountEmails()\n if (remaining.length > 0) {\n info(`Active account: ${manager.getActiveEmail() || 'none'}`)\n }\n } else {\n warn(`Could not log out of ${email}.`)\n }\n return\n }\n \n // Logout active account (default behavior)\n const activeEmail = manager.getActiveEmail()\n \n if (!activeEmail) {\n warn('Not logged in.')\n return\n }\n \n const removed = manager.removeAccount(activeEmail)\n resetTokenManager()\n \n if (removed) {\n success(`Logged out of ${activeEmail}.`)\n \n const remaining = manager.getAccountEmails()\n if (remaining.length > 0) {\n const newActive = manager.getActiveEmail()\n info(`Switched to: ${newActive}`)\n }\n } else {\n warn('Could not delete account.')\n }\n}\n","/**\n * Token masking utility\n */\n\n/**\n * Mask a token for display, showing first 6 and last 4 characters\n * @example maskToken('abc123xyz789secret') => 'abc123...cret'\n */\nexport function maskToken(token: string): string {\n if (!token) return ''\n if (token.length <= 10) return '***'\n \n const first = token.slice(0, 6)\n const last = token.slice(-4)\n return `${first}...${last}`\n}\n\n/**\n * Mask an email for display\n * @example maskEmail('user@example.com') => 'us**@example.com'\n */\nexport function maskEmail(email: string): string {\n if (!email) return ''\n \n const [local, domain] = email.split('@')\n if (!domain) return email\n \n if (local.length <= 2) {\n return `${local[0] || ''}**@${domain}`\n }\n \n return `${local.slice(0, 2)}**@${domain}`\n}\n","/**\n * Status command - show current login status\n */\n\nimport { getTokenManager, getTokenManagerForAccount } from '../google/token-manager.js'\nimport { getAccountManager } from '../accounts/index.js'\nimport { maskEmail, maskToken } from '../core/mask.js'\nimport { info, warn } from '../core/logger.js'\nimport { isDebugMode } from '../core/logger.js'\nimport Table from 'cli-table3'\n\ninterface StatusOptions {\n all?: boolean\n account?: string\n}\n\n/**\n * Show status for a single account\n */\nfunction showSingleAccountStatus(email?: string): void {\n const tokenManager = email \n ? getTokenManagerForAccount(email)\n : getTokenManager()\n \n console.log()\n console.log('📍 Antigravity Usage Status')\n console.log('─'.repeat(40))\n \n if (!tokenManager.isLoggedIn()) {\n warn('Not logged in')\n console.log()\n info('Run `antigravity-usage login` to authenticate.')\n console.log()\n return\n }\n \n const accountEmail = tokenManager.getEmail()\n const expiresAt = tokenManager.getExpiresAt()\n const isExpired = tokenManager.isTokenExpired()\n \n console.log(`✅ Logged in: Yes`)\n \n if (accountEmail) {\n console.log(`📧 Email: ${maskEmail(accountEmail)}`)\n }\n \n if (expiresAt) {\n const expiryStr = expiresAt.toLocaleString()\n const status = isExpired ? ' (expired/expiring soon)' : ''\n console.log(`⏰ Token expires: ${expiryStr}${status}`)\n }\n \n // Debug mode shows more detail\n if (isDebugMode()) {\n const tokens = email \n ? getAccountManager().getTokens(email)\n : getAccountManager().getActiveTokens()\n if (tokens) {\n console.log()\n console.log('Debug info:')\n console.log(` Access token: ${maskToken(tokens.accessToken)}`)\n console.log(` Refresh token: ${maskToken(tokens.refreshToken)}`)\n }\n }\n \n console.log()\n}\n\n/**\n * Show status for all accounts\n */\nfunction showAllAccountsStatus(): void {\n const manager = getAccountManager()\n const emails = manager.getAccountEmails()\n const activeEmail = manager.getActiveEmail()\n \n console.log()\n console.log('📍 Antigravity Usage Status - All Accounts')\n console.log('═'.repeat(60))\n \n if (emails.length === 0) {\n warn('No accounts found.')\n console.log()\n info('Run `antigravity-usage login` to add an account.')\n console.log()\n return\n }\n \n const table = new Table({\n head: ['Account', 'Logged In', 'Token Expiry'],\n style: {\n head: ['cyan'],\n border: ['gray']\n },\n colWidths: [30, 12, 28]\n })\n \n for (const email of emails) {\n const tokenManager = getTokenManagerForAccount(email)\n const isActive = email === activeEmail\n const nameDisplay = isActive ? `${email} [*]` : email\n \n if (tokenManager.isLoggedIn()) {\n const expiresAt = tokenManager.getExpiresAt()\n const isExpired = tokenManager.isTokenExpired()\n \n let expiryDisplay = '-'\n if (expiresAt) {\n expiryDisplay = expiresAt.toLocaleString()\n if (isExpired) {\n expiryDisplay = `⚠️ ${expiryDisplay}`\n }\n }\n \n table.push([\n nameDisplay,\n '✅',\n expiryDisplay\n ])\n } else {\n table.push([\n nameDisplay,\n '❌',\n 'Invalid or missing'\n ])\n }\n }\n \n console.log(table.toString())\n console.log()\n console.log('[*] = active account')\n console.log()\n}\n\nexport function statusCommand(options: StatusOptions = {}): void {\n if (options.all) {\n showAllAccountsStatus()\n return\n }\n \n if (options.account) {\n const manager = getAccountManager()\n if (!manager.hasAccount(options.account)) {\n warn(`Account '${options.account}' not found.`)\n return\n }\n showSingleAccountStatus(options.account)\n return\n }\n \n showSingleAccountStatus()\n}\n","/**\n * Google Cloud Code API client\n */\n\nimport { randomUUID } from 'crypto'\nimport { debug } from '../core/logger.js'\nimport { APIError, AuthenticationError, NetworkError, RateLimitError } from '../core/errors.js'\nimport type { TokenManager } from './token-manager.js'\n\n// Base URLs - try production first, then sandbox (matching example.ts)\nconst BASE_URLS = [\n 'https://cloudcode-pa.googleapis.com',\n 'https://daily-cloudcode-pa.sandbox.googleapis.com'\n]\nconst BASE_URL = BASE_URLS[0] // Default for non-trigger API calls\nconst USER_AGENT = 'antigravity'\n\n// Retry configuration (matching example.ts)\nconst MAX_TRIGGER_ATTEMPTS = 3\nconst STREAM_PATH = '/v1internal:streamGenerateContent?alt=sse'\n\n// System prompt - MUST match exact Cockpit extension format\nconst SYSTEM_PROMPT = 'You are Antigravity, a powerful agentic AI coding assistant designed by the Google Deepmind team working on Advanced Agentic Coding. You are pair programming with a USER to solve their coding task. The task may require creating a new codebase, modifying or debugging an existing codebase, or simply answering a question.**Absolute paths only****Proactiveness**'\n\n// Standard metadata for Cloud Code API calls\nconst METADATA = {\n ideType: 'ANTIGRAVITY',\n platform: 'PLATFORM_UNSPECIFIED',\n pluginType: 'GEMINI'\n}\n\n/**\n * Raw API response types (based on extension code patterns)\n */\nexport interface LoadCodeAssistResponse {\n codeAssistEnabled?: boolean\n planInfo?: {\n monthlyPromptCredits?: number\n planType?: string\n }\n availablePromptCredits?: number\n cloudaicompanionProject?: string | { id?: string }\n currentTier?: {\n id?: string\n name?: string\n description?: string\n }\n paidTier?: {\n id?: string\n }\n allowedTiers?: Array<{ id?: string; isDefault?: boolean }>\n}\n\n/**\n * Model info in the response - keyed by model ID\n */\nexport interface ModelInfo {\n displayName?: string\n model?: string\n label?: string\n quotaInfo?: {\n remainingFraction?: number\n resetTime?: string\n isExhausted?: boolean\n }\n maxTokens?: number\n recommended?: boolean\n supportsImages?: boolean\n supportsThinking?: boolean\n modelProvider?: string\n}\n\n/**\n * The actual response structure - models is an object, not an array\n */\nexport interface FetchAvailableModelsResponse {\n models?: Record<string, ModelInfo>\n defaultAgentModelId?: string\n}\n\n/**\n * Cloud Code API client\n */\nexport class CloudCodeClient {\n private projectId?: string\n \n constructor(private tokenManager: TokenManager) {\n // Initialize project ID from cached tokens (stored during login/quota fetch)\n this.projectId = tokenManager.getProjectId()\n }\n \n /**\n * Make an authenticated API request\n */\n private async request<T>(endpoint: string, body?: unknown): Promise<T> {\n const token = await this.tokenManager.getValidAccessToken()\n const url = `${BASE_URL}${endpoint}`\n \n debug('cloudcode', `Calling ${endpoint}`)\n \n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n 'User-Agent': USER_AGENT\n },\n body: body ? JSON.stringify(body) : undefined\n })\n \n debug('cloudcode', `Response status: ${response.status}`)\n \n if (response.status === 401 || response.status === 403) {\n const errorBody = await response.text()\n debug('cloudcode', `Auth error body: ${errorBody}`)\n throw new AuthenticationError('Authentication failed. Please run: antigravity-usage login')\n }\n \n if (response.status === 429) {\n const retryAfter = response.headers.get('retry-after')\n const retryMs = retryAfter ? parseInt(retryAfter) * 1000 : undefined\n throw new RateLimitError('Rate limited by Google API', retryMs)\n }\n \n if (response.status >= 500) {\n throw new APIError(`Server error: ${response.status}`, response.status)\n }\n \n if (!response.ok) {\n const errorText = await response.text()\n debug('cloudcode', 'API error response', errorText)\n throw new APIError(`API request failed: ${response.status}`, response.status)\n }\n \n const data = await response.json() as T\n debug('cloudcode', 'API call successful')\n return data\n } catch (err) {\n if (err instanceof AuthenticationError || \n err instanceof RateLimitError || \n err instanceof APIError) {\n throw err\n }\n \n if (err instanceof TypeError && err.message.includes('fetch')) {\n throw new NetworkError('Network error. Please check your connection.')\n }\n \n throw err\n }\n }\n \n /**\n * Load code assist status and plan info\n * Also extracts project ID for subsequent calls\n */\n async loadCodeAssist(): Promise<LoadCodeAssistResponse> {\n // Use complete metadata as per working implementation\n const response = await this.request<LoadCodeAssistResponse>('/v1internal:loadCodeAssist', {\n metadata: METADATA\n })\n \n // Store project ID for fetchAvailableModels\n // Handle both string and object formats\n if (response.cloudaicompanionProject) {\n if (typeof response.cloudaicompanionProject === 'string') {\n this.projectId = response.cloudaicompanionProject\n } else if (response.cloudaicompanionProject.id) {\n this.projectId = response.cloudaicompanionProject.id\n }\n debug('cloudcode', `Project ID: ${this.projectId}`)\n }\n \n return response\n }\n \n /**\n * Extract project ID from loadCodeAssist response\n */\n private extractProjectId(response: LoadCodeAssistResponse): void {\n // Try multiple possible field names\n const projectId = response.cloudaicompanionProject \n || (response as any).project \n || (response as any).projectId\n || (response as any).cloudProject\n \n if (projectId && typeof projectId === 'string' && projectId.length > 0) {\n this.projectId = projectId\n debug('cloudcode', `Project ID extracted: ${this.projectId}`)\n } else {\n debug('cloudcode', 'No project ID found in response')\n }\n }\n \n /**\n * Resolve project ID with onboarding retry if needed\n * This is the recommended way to get projectId reliably\n */\n async resolveProjectId(maxRetries: number = 5, retryDelayMs: number = 2000): Promise<string | undefined> {\n // If already have projectId, return it\n if (this.projectId) {\n debug('cloudcode', `Using cached project ID: ${this.projectId}`)\n return this.projectId\n }\n \n // Try loading first\n const loadResponse = await this.loadCodeAssist()\n if (this.projectId) {\n return this.projectId\n }\n \n // Project ID not found - may need onboarding\n debug('cloudcode', 'Project ID not found, attempting onboarding...')\n \n // Pick onboarding tier from allowedTiers\n const tiers = loadResponse.allowedTiers || []\n let tierId: string | undefined\n \n // Prefer default tier, then paidTier, then first available\n const defaultTier = tiers.find((t: any) => t.isDefault)\n if (defaultTier) {\n tierId = defaultTier.id\n } else if (loadResponse.paidTier?.id) {\n tierId = loadResponse.paidTier.id\n } else if ((loadResponse as any).currentTier?.id) {\n tierId = (loadResponse as any).currentTier.id\n } else if (tiers.length > 0) {\n tierId = tiers[0].id\n }\n \n if (!tierId) {\n debug('cloudcode', 'No tier available for onboarding')\n return undefined\n }\n \n debug('cloudcode', `Onboarding with tier: ${tierId}`)\n \n // Try onboarding (call to select/confirm tier)\n try {\n await this.request('/v1internal:onboardUser', {\n tierId,\n metadata: { \n ideType: 'ANTIGRAVITY',\n platform: 'PLATFORM_UNSPECIFIED',\n pluginType: 'GEMINI'\n }\n })\n } catch (err) {\n debug('cloudcode', 'Onboarding call failed (may be expected):', err)\n // Continue with retry loop anyway\n }\n \n // Retry loop to get project ID\n for (let i = 0; i < maxRetries; i++) {\n debug('cloudcode', `Retry ${i + 1}/${maxRetries} for project ID...`)\n \n // Wait before retry\n await new Promise(resolve => setTimeout(resolve, retryDelayMs))\n \n // Try loading again\n await this.loadCodeAssist()\n \n if (this.projectId) {\n debug('cloudcode', `Project ID resolved after ${i + 1} retries: ${this.projectId}`)\n return this.projectId\n }\n }\n \n debug('cloudcode', 'Failed to resolve project ID after all retries')\n return undefined\n }\n \n /**\n * Fetch available models with quota info\n * Requires project ID from loadCodeAssist\n */\n async fetchAvailableModels(): Promise<FetchAvailableModelsResponse> {\n const body = this.projectId ? { project: this.projectId } : {}\n return this.request<FetchAvailableModelsResponse>('/v1internal:fetchAvailableModels', body)\n }\n \n /**\n * Generate content using a specific model (Agent Request Format)\n * Used for wake-up triggers to warm up models\n * \n * Per docs/trigger.md, must use the agent request format with:\n * - project: Cloud Code project ID\n * - requestId: unique ID\n * - model: model ID\n * - userAgent: \"antigravity\"\n * - requestType: \"agent\"\n * - request: contains contents, session_id, systemInstruction, generationConfig\n * \n * @param modelId Model ID to use\n * @param prompt User prompt to send\n * @param maxOutputTokens Maximum tokens to generate (0 = no limit)\n * @returns Generated text and optional token usage\n */\n async generateContent(\n modelId: string, \n prompt: string, \n maxOutputTokens?: number\n ): Promise<{ text: string; tokensUsed?: { prompt: number; completion: number; total: number } }> {\n debug('cloudcode', `Generating content with model: ${modelId}`)\n debug('cloudcode', `Current projectId: ${this.projectId}`)\n \n // CRITICAL: Always warm up session with loadCodeAssist before trigger request\n // This is required for the API to accept our requests (matching example.ts)\n debug('cloudcode', 'Warming up session with loadCodeAssist...')\n try {\n await this.loadCodeAssist()\n debug('cloudcode', `Session warmed up, projectId: ${this.projectId}`)\n } catch (err) {\n debug('cloudcode', 'Warmup failed (continuing anyway):', err)\n }\n \n // Generate unique IDs\n const requestId = randomUUID()\n const sessionId = randomUUID()\n \n // System instruction - MUST match exact Cockpit extension format\n const systemInstruction = {\n parts: [{ text: SYSTEM_PROMPT }]\n }\n \n // Generation config\n const generationConfig: Record<string, unknown> = {\n temperature: 0\n }\n if (maxOutputTokens && maxOutputTokens > 0) {\n generationConfig.maxOutputTokens = maxOutputTokens\n }\n \n // Build agent request body per docs/trigger.md\n // Project may be optional if the API can infer it from the token\n const body: Record<string, unknown> = {\n requestId,\n model: modelId,\n userAgent: 'antigravity',\n requestType: 'agent',\n request: {\n contents: [{\n role: 'user',\n parts: [{ text: prompt }]\n }],\n session_id: sessionId,\n systemInstruction,\n generationConfig\n }\n }\n \n // Add project only if we have one\n if (this.projectId) {\n body.project = this.projectId\n debug('cloudcode', `Using project ID: ${this.projectId}`)\n } else {\n debug('cloudcode', 'Sending request WITHOUT project ID')\n }\n \n debug('cloudcode', `Request body:`, JSON.stringify(body, null, 2))\n \n // Get fresh access token\n const token = await this.tokenManager.getValidAccessToken()\n \n // Helper: Calculate backoff delay (matching example.ts)\n const getBackoffDelay = (attempt: number): number => {\n const raw = 500 * Math.pow(2, attempt - 2)\n const jitter = Math.random() * 100\n return Math.min(raw + jitter, 4000)\n }\n \n // Helper: Sleep function\n const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))\n \n // Helper: Parse SSE response\n const parseSSEResponse = (sseText: string): { text: string; tokensUsed?: { prompt: number; completion: number; total: number } } => {\n let fullText = ''\n let tokensUsed: { prompt: number; completion: number; total: number } | undefined\n \n for (const line of sseText.split('\\n')) {\n if (line.startsWith('data: ')) {\n const jsonStr = line.substring(6)\n if (jsonStr.trim() === '[DONE]') continue\n \n try {\n const data = JSON.parse(jsonStr)\n const candidateText = data.candidates?.[0]?.content?.parts?.[0]?.text\n if (candidateText) {\n fullText += candidateText\n }\n if (data.usageMetadata) {\n tokensUsed = {\n prompt: data.usageMetadata.promptTokenCount || 0,\n completion: data.usageMetadata.candidatesTokenCount || 0,\n total: data.usageMetadata.totalTokenCount || 0\n }\n }\n } catch {\n // Ignore parse errors\n }\n }\n }\n \n return { text: fullText, tokensUsed }\n }\n \n // CRITICAL: Try each base URL with retries (matching example.ts EXACTLY)\n for (const baseUrl of BASE_URLS) {\n for (let attempt = 1; attempt <= MAX_TRIGGER_ATTEMPTS; attempt++) {\n // Backoff BEFORE request (except first attempt) - matching example.ts\n if (attempt > 1) {\n const delay = getBackoffDelay(attempt)\n debug('cloudcode', `Retry ${attempt}/${MAX_TRIGGER_ATTEMPTS} in ${Math.round(delay)}ms...`)\n await sleep(delay)\n }\n \n const url = `${baseUrl}${STREAM_PATH}`\n debug('cloudcode', `Attempt ${attempt}/${MAX_TRIGGER_ATTEMPTS} on ${baseUrl}`)\n \n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'User-Agent': USER_AGENT,\n 'Content-Type': 'application/json',\n 'Accept-Encoding': 'gzip' // CRITICAL: Must match example.ts\n },\n body: JSON.stringify(body)\n })\n \n const text = await response.text()\n debug('cloudcode', `Response ${response.status}`)\n debug('cloudcode', `Response text: ${text.slice(0, 500)}`)\n \n // Handle retryable errors (429 or 5xx) - matching example.ts\n if (response.status === 429 || response.status >= 500) {\n debug('cloudcode', `${response.status} - retryable`)\n if (attempt === MAX_TRIGGER_ATTEMPTS) {\n debug('cloudcode', 'Max attempts on this URL, trying next...')\n break // Try next base URL\n }\n continue // Retry on same URL\n }\n \n // Success!\n if (response.ok) {\n debug('cloudcode', 'Request succeeded!')\n const parsed = parseSSEResponse(text)\n debug('cloudcode', `Generated ${parsed.text.length} chars, tokens: ${parsed.tokensUsed?.total || 'unknown'}`)\n return parsed\n }\n \n // Non-retryable error (4xx except 429)\n debug('cloudcode', `Non-retryable error: ${response.status}`)\n throw new Error(`API request failed: ${response.status} - ${text}`)\n \n } catch (err) {\n // Network or other error\n if (err instanceof Error && !err.message.startsWith('API request failed')) {\n debug('cloudcode', `Network error: ${err.message}`)\n if (attempt === MAX_TRIGGER_ATTEMPTS) {\n debug('cloudcode', 'Max attempts on this URL, trying next...')\n break // Try next base URL\n }\n continue // Retry on same URL\n }\n throw err // Re-throw API errors\n }\n }\n }\n \n // All URLs and retries exhausted\n throw new Error('All trigger attempts failed across all base URLs')\n }\n}\n","/**\n * Parser for Cloud Code API responses\n */\n\nimport { debug } from '../core/logger.js'\nimport type { QuotaSnapshot, ModelQuotaInfo, PromptCreditsInfo } from '../quota/types.js'\nimport type { LoadCodeAssistResponse, FetchAvailableModelsResponse, ModelInfo } from './cloudcode.js'\n\n/**\n * Parse reset time string to milliseconds until reset\n */\nfunction parseResetTime(resetTime?: string): number | undefined {\n if (!resetTime) return undefined\n\n try {\n const resetDate = new Date(resetTime)\n const now = Date.now()\n const diff = resetDate.getTime() - now\n return diff > 0 ? diff : undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * Parse model info into ModelQuotaInfo\n */\nfunction parseModelInfo(modelId: string, model: ModelInfo): ModelQuotaInfo {\n const quotaInfo = model.quotaInfo\n\n return {\n label: model.displayName || model.label || modelId,\n modelId: modelId,\n remainingPercentage: quotaInfo?.remainingFraction,\n isExhausted: quotaInfo?.isExhausted ?? (quotaInfo?.remainingFraction === 0),\n resetTime: quotaInfo?.resetTime,\n timeUntilResetMs: parseResetTime(quotaInfo?.resetTime),\n isAutocompleteOnly: modelId.includes('gemini-2.5') || (model.displayName || '').includes('Gemini 2.5')\n }\n}\n\n/**\n * Parse prompt credits from loadCodeAssist response\n */\nfunction parsePromptCredits(response: LoadCodeAssistResponse): PromptCreditsInfo | undefined {\n const monthly = response.planInfo?.monthlyPromptCredits\n const available = response.availablePromptCredits\n\n if (monthly === undefined || available === undefined) {\n return undefined\n }\n\n const used = monthly - available\n const usedPercentage = monthly > 0 ? used / monthly : 0\n const remainingPercentage = monthly > 0 ? available / monthly : 0\n\n return {\n available,\n monthly,\n usedPercentage,\n remainingPercentage\n }\n}\n\n/**\n * Check if a model should be shown in quota display\n * Filter out internal models and only show recommended ones\n */\nfunction shouldShowModel(modelId: string, model: ModelInfo): boolean {\n // Skip internal models\n if (modelId.startsWith('chat_') || modelId.startsWith('tab_')) {\n return false\n }\n // Skip image generation models\n if (modelId.includes('image')) {\n return false\n }\n // Skip internal/experimental models\n if (modelId.startsWith('rev')) {\n return false\n }\n // Skip lite models that are just for specific features\n if (modelId.includes('mquery') || modelId.includes('lite')) {\n return false\n }\n // Only show models with quota info\n if (!model.quotaInfo) {\n return false\n }\n return true\n}\n\n/**\n * Parse API responses into a QuotaSnapshot\n */\nexport function parseQuotaSnapshot(\n codeAssistResponse: LoadCodeAssistResponse,\n modelsResponse: FetchAvailableModelsResponse,\n email?: string\n): QuotaSnapshot {\n debug('parser', 'Parsing quota snapshot')\n\n const promptCredits = parsePromptCredits(codeAssistResponse)\n const planType = codeAssistResponse.planInfo?.planType\n\n // Models is now an object keyed by model ID\n const modelsMap = modelsResponse.models || {}\n const models: ModelQuotaInfo[] = []\n\n for (const [modelId, modelInfo] of Object.entries(modelsMap)) {\n if (shouldShowModel(modelId, modelInfo)) {\n models.push(parseModelInfo(modelId, modelInfo))\n }\n }\n\n // Sort by displayName\n models.sort((a, b) => a.label.localeCompare(b.label))\n\n debug('parser', `Parsed ${models.length} models`)\n\n return {\n timestamp: new Date().toISOString(),\n method: 'google',\n email,\n planType,\n promptCredits,\n models\n }\n}\n","/**\n * Process detector - finds running Antigravity language server processes\n */\n\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\nimport { debug } from '../core/logger.js'\n\nconst execAsync = promisify(exec)\n\nexport interface AntigravityProcessInfo {\n pid: number\n csrfToken?: string\n extensionServerPort?: number\n commandLine: string\n}\n\n/**\n * Detects running Antigravity language server processes\n * Returns process info including PID and extracted command-line arguments\n */\nexport async function detectAntigravityProcess(): Promise<AntigravityProcessInfo | null> {\n const platform = process.platform\n \n debug('process-detector', `Detecting Antigravity process on platform: ${platform}`)\n \n if (platform === 'win32') {\n return detectOnWindows()\n } else {\n // macOS and Linux use similar commands\n return detectOnUnix()\n }\n}\n\n/**\n * Detect Antigravity process on Unix-like systems (macOS, Linux)\n */\nasync function detectOnUnix(): Promise<AntigravityProcessInfo | null> {\n try {\n // Use ps to list all processes with full command line\n // Look for processes containing 'antigravity' in their command\n const { stdout } = await execAsync('ps aux')\n \n const lines = stdout.split('\\n')\n \n for (const line of lines) {\n // Look for language server process indicators\n // Common patterns: antigravity, language-server, lsp\n if (line.toLowerCase().includes('antigravity') && \n (line.includes('language-server') || line.includes('lsp') || line.includes('server'))) {\n \n debug('process-detector', `Found potential Antigravity process: ${line}`)\n \n const processInfo = parseUnixProcessLine(line)\n if (processInfo) {\n return processInfo\n }\n }\n }\n \n debug('process-detector', 'No Antigravity process found')\n return null\n } catch (err) {\n debug('process-detector', 'Error detecting process on Unix', err)\n return null\n }\n}\n\n/**\n * Parse a Unix ps output line to extract process info\n */\nfunction parseUnixProcessLine(line: string): AntigravityProcessInfo | null {\n // ps aux format: USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND...\n const parts = line.trim().split(/\\s+/)\n \n if (parts.length < 11) {\n return null\n }\n \n const pid = parseInt(parts[1], 10)\n if (isNaN(pid)) {\n return null\n }\n \n // Command is everything from index 10 onwards\n const commandLine = parts.slice(10).join(' ')\n \n // Extract arguments from command line\n const csrfToken = extractArgument(commandLine, '--csrf_token')\n const extensionServerPort = extractArgument(commandLine, '--extension_server_port')\n \n return {\n pid,\n csrfToken: csrfToken || undefined,\n extensionServerPort: extensionServerPort ? parseInt(extensionServerPort, 10) : undefined,\n commandLine\n }\n}\n\n/**\n * Detect Antigravity process on Windows\n */\nasync function detectOnWindows(): Promise<AntigravityProcessInfo | null> {\n try {\n // Use WMIC to get process details with command line\n const { stdout } = await execAsync(\n 'wmic process where \"name like \\'%antigravity%\\' or commandline like \\'%antigravity%\\'\" get processid,commandline /format:csv',\n { maxBuffer: 10 * 1024 * 1024 } // 10MB buffer for long command lines\n )\n \n const lines = stdout.split('\\n').filter(line => line.trim() && !line.includes('Node,CommandLine,ProcessId'))\n \n for (const line of lines) {\n // CSV format: Node,CommandLine,ProcessId\n const parts = line.split(',')\n if (parts.length >= 3) {\n const commandLine = parts.slice(1, -1).join(',') // Command line might contain commas\n const pid = parseInt(parts[parts.length - 1].trim(), 10)\n \n if (!isNaN(pid) && commandLine.toLowerCase().includes('antigravity')) {\n debug('process-detector', `Found Antigravity process on Windows: PID ${pid}`)\n \n const csrfToken = extractArgument(commandLine, '--csrf_token')\n const extensionServerPort = extractArgument(commandLine, '--extension_server_port')\n \n return {\n pid,\n csrfToken: csrfToken || undefined,\n extensionServerPort: extensionServerPort ? parseInt(extensionServerPort, 10) : undefined,\n commandLine\n }\n }\n }\n }\n \n // Fallback: try PowerShell if WMIC doesn't work\n return await detectOnWindowsPowerShell()\n } catch (err) {\n debug('process-detector', 'Error detecting process on Windows with WMIC, trying PowerShell', err)\n return await detectOnWindowsPowerShell()\n }\n}\n\n/**\n * Fallback Windows detection using PowerShell\n */\nasync function detectOnWindowsPowerShell(): Promise<AntigravityProcessInfo | null> {\n try {\n const { stdout } = await execAsync(\n 'powershell -Command \"Get-Process | Where-Object { $_.ProcessName -like \\'*antigravity*\\' } | Select-Object Id, ProcessName | ConvertTo-Json\"'\n )\n \n if (!stdout.trim()) {\n return null\n }\n \n const processes = JSON.parse(stdout)\n const processList = Array.isArray(processes) ? processes : [processes]\n \n for (const proc of processList) {\n if (proc.Id) {\n // Get command line for this process\n const { stdout: cmdLine } = await execAsync(\n `powershell -Command \"(Get-CimInstance Win32_Process -Filter 'ProcessId = ${proc.Id}').CommandLine\"`\n )\n \n const commandLine = cmdLine.trim()\n const csrfToken = extractArgument(commandLine, '--csrf_token')\n const extensionServerPort = extractArgument(commandLine, '--extension_server_port')\n \n return {\n pid: proc.Id,\n csrfToken: csrfToken || undefined,\n extensionServerPort: extensionServerPort ? parseInt(extensionServerPort, 10) : undefined,\n commandLine\n }\n }\n }\n \n return null\n } catch (err) {\n debug('process-detector', 'Error detecting process on Windows with PowerShell', err)\n return null\n }\n}\n\n/**\n * Extract argument value from command line\n * Supports formats: --arg=value and --arg value\n */\nfunction extractArgument(commandLine: string, argName: string): string | null {\n // Try --arg=value format\n const eqRegex = new RegExp(`${argName}=([^\\\\s\"']+|\"[^\"]*\"|'[^']*')`, 'i')\n const eqMatch = commandLine.match(eqRegex)\n if (eqMatch) {\n return eqMatch[1].replace(/^[\"']|[\"']$/g, '') // Remove quotes\n }\n \n // Try --arg value format\n const spaceRegex = new RegExp(`${argName}\\\\s+([^\\\\s\"']+|\"[^\"]*\"|'[^']*')`, 'i')\n const spaceMatch = commandLine.match(spaceRegex)\n if (spaceMatch) {\n return spaceMatch[1].replace(/^[\"']|[\"']$/g, '') // Remove quotes\n }\n \n return null\n}\n","/**\n * Port detective - discovers listening ports for a given process\n */\n\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\nimport { debug } from '../core/logger.js'\n\nconst execAsync = promisify(exec)\n\n/**\n * Discovers which ports a process is listening on\n * @param pid Process ID to check\n * @returns Array of port numbers the process is listening on\n */\nexport async function discoverPorts(pid: number): Promise<number[]> {\n const platform = process.platform\n \n debug('port-detective', `Discovering ports for PID ${pid} on platform: ${platform}`)\n \n if (platform === 'win32') {\n return discoverPortsOnWindows(pid)\n } else if (platform === 'darwin') {\n return discoverPortsOnMacOS(pid)\n } else {\n return discoverPortsOnLinux(pid)\n }\n}\n\n/**\n * Discover listening ports on macOS using lsof\n */\nasync function discoverPortsOnMacOS(pid: number): Promise<number[]> {\n try {\n // lsof -nP -iTCP -sTCP:LISTEN -a -p <PID>\n const { stdout } = await execAsync(`lsof -nP -iTCP -sTCP:LISTEN -a -p ${pid}`)\n \n const ports: number[] = []\n const lines = stdout.split('\\n')\n \n for (const line of lines) {\n // Format: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\n // NAME column contains: *:PORT or IP:PORT (LISTEN)\n const match = line.match(/:(\\d+)\\s+\\(LISTEN\\)/)\n if (match) {\n const port = parseInt(match[1], 10)\n if (!isNaN(port) && !ports.includes(port)) {\n ports.push(port)\n }\n }\n }\n \n debug('port-detective', `Found ports on macOS: ${ports.join(', ')}`)\n return ports\n } catch (err) {\n debug('port-detective', 'Error discovering ports on macOS', err)\n return []\n }\n}\n\n/**\n * Discover listening ports on Linux using ss or netstat\n */\nasync function discoverPortsOnLinux(pid: number): Promise<number[]> {\n try {\n // Try ss first (modern)\n const { stdout } = await execAsync(`ss -tlnp | grep \"pid=${pid},\"`)\n \n const ports: number[] = []\n const lines = stdout.split('\\n')\n \n for (const line of lines) {\n // Format: State Recv-Q Send-Q Local Address:Port Peer Address:Port Process\n const match = line.match(/:(\\d+)\\s/)\n if (match) {\n const port = parseInt(match[1], 10)\n if (!isNaN(port) && !ports.includes(port)) {\n ports.push(port)\n }\n }\n }\n \n if (ports.length > 0) {\n debug('port-detective', `Found ports on Linux (ss): ${ports.join(', ')}`)\n return ports\n }\n \n // Fallback to netstat\n return await discoverPortsOnLinuxNetstat(pid)\n } catch {\n // ss might not find anything, try netstat\n return await discoverPortsOnLinuxNetstat(pid)\n }\n}\n\n/**\n * Fallback Linux port discovery using netstat\n */\nasync function discoverPortsOnLinuxNetstat(pid: number): Promise<number[]> {\n try {\n const { stdout } = await execAsync(`netstat -tlnp 2>/dev/null | grep \"${pid}/\"`)\n \n const ports: number[] = []\n const lines = stdout.split('\\n')\n \n for (const line of lines) {\n // Format: Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program\n const match = line.match(/:(\\d+)\\s/)\n if (match) {\n const port = parseInt(match[1], 10)\n if (!isNaN(port) && !ports.includes(port)) {\n ports.push(port)\n }\n }\n }\n \n debug('port-detective', `Found ports on Linux (netstat): ${ports.join(', ')}`)\n return ports\n } catch (err) {\n debug('port-detective', 'Error discovering ports on Linux', err)\n return []\n }\n}\n\n/**\n * Discover listening ports on Windows using netstat\n */\nasync function discoverPortsOnWindows(pid: number): Promise<number[]> {\n try {\n // netstat -ano shows all connections with PIDs\n const { stdout } = await execAsync('netstat -ano')\n \n const ports: number[] = []\n const lines = stdout.split('\\n')\n \n for (const line of lines) {\n // Format: Proto Local Address Foreign Address State PID\n // Look for LISTENING state and matching PID\n if (line.includes('LISTENING')) {\n const parts = line.trim().split(/\\s+/)\n const linePid = parseInt(parts[parts.length - 1], 10)\n \n if (linePid === pid) {\n // Extract port from local address (format: IP:PORT or [::]:PORT)\n const localAddr = parts[1]\n const portMatch = localAddr.match(/:(\\d+)$/)\n if (portMatch) {\n const port = parseInt(portMatch[1], 10)\n if (!isNaN(port) && !ports.includes(port)) {\n ports.push(port)\n }\n }\n }\n }\n }\n \n debug('port-detective', `Found ports on Windows: ${ports.join(', ')}`)\n return ports\n } catch (err) {\n debug('port-detective', 'Error discovering ports on Windows', err)\n return []\n }\n}\n","/**\n * Port prober - probes ports to find the Connect API endpoint\n */\n\nimport https from 'https'\nimport http from 'http'\nimport { debug } from '../core/logger.js'\n\nexport interface ProbeResult {\n baseUrl: string\n protocol: 'https' | 'http'\n port: number\n}\n\n/**\n * Probes ports to find a working Connect API endpoint\n * Tries HTTPS first (with self-signed cert handling), then HTTP\n * @param ports Array of port numbers to probe\n * @param csrfToken Optional CSRF token for authentication\n * @param timeout Timeout per probe in ms (default 500ms)\n * @returns ProbeResult with working endpoint, or null if none found\n */\nexport async function probeForConnectAPI(ports: number[], csrfToken?: string, timeout = 500): Promise<ProbeResult | null> {\n debug('port-prober', `Probing ${ports.length} ports: ${ports.join(', ')}`)\n \n // Probe all ports concurrently\n const probePromises = ports.map(port => probePort(port, csrfToken, timeout))\n const results = await Promise.allSettled(probePromises)\n \n // Find first successful probe\n for (let i = 0; i < results.length; i++) {\n const result = results[i]\n if (result.status === 'fulfilled' && result.value) {\n debug('port-prober', `Found working endpoint: ${result.value.baseUrl}`)\n return result.value\n }\n }\n \n debug('port-prober', 'No working Connect API endpoint found')\n return null\n}\n\n/**\n * Probe a single port for Connect API\n * Tries HTTPS first, then HTTP\n */\nasync function probePort(port: number, csrfToken?: string, timeout = 500): Promise<ProbeResult | null> {\n // Try HTTPS first (language server typically uses self-signed certs)\n const httpsResult = await probeHttps(port, timeout, csrfToken)\n if (httpsResult) {\n return httpsResult\n }\n \n // Fallback to HTTP\n const httpResult = await probeHttp(port, timeout)\n if (httpResult) {\n return httpResult\n }\n \n return null\n}\n\n/**\n * Probe a port with HTTPS (allowing self-signed certificates)\n * Uses Connect RPC GetUnleashData endpoint to verify it's the correct port\n */\nfunction probeHttps(port: number, timeout: number, csrfToken?: string): Promise<ProbeResult | null> {\n return new Promise((resolve) => {\n const options: https.RequestOptions = {\n hostname: '127.0.0.1',\n port,\n path: '/exa.language_server_pb.LanguageServerService/GetUnleashData',\n method: 'POST',\n timeout,\n rejectUnauthorized: false, // Allow self-signed certificates\n headers: {\n 'Content-Type': 'application/json',\n 'Connect-Protocol-Version': '1',\n ...(csrfToken ? { 'X-Codeium-Csrf-Token': csrfToken } : {})\n }\n }\n \n const req = https.request(options, (res) => {\n // Check for successful response\n if (res.statusCode === 200) {\n debug('port-prober', `HTTPS Connect RPC probe on port ${port}: status ${res.statusCode} - valid connect port`)\n resolve({\n baseUrl: `https://127.0.0.1:${port}`,\n protocol: 'https',\n port\n })\n } else {\n debug('port-prober', `HTTPS probe on port ${port}: status ${res.statusCode} - not connect port`)\n resolve(null)\n }\n \n // Consume response data to free up memory\n res.resume()\n })\n \n req.on('error', (err) => {\n debug('port-prober', `HTTPS probe on port ${port} failed: ${err.message}`)\n resolve(null)\n })\n \n req.on('timeout', () => {\n debug('port-prober', `HTTPS probe on port ${port} timed out`)\n req.destroy()\n resolve(null)\n })\n \n // Send the Connect RPC request body\n req.write(JSON.stringify({ wrapper_data: {} }))\n req.end()\n })\n}\n\n/**\n * Probe a port with HTTP\n */\nfunction probeHttp(port: number, timeout: number): Promise<ProbeResult | null> {\n return new Promise((resolve) => {\n const options: http.RequestOptions = {\n hostname: 'localhost',\n port,\n path: '/',\n method: 'GET',\n timeout,\n }\n \n const req = http.request(options, (res) => {\n // Any response (even 404) means server is there\n debug('port-prober', `HTTP probe on port ${port}: status ${res.statusCode}`)\n resolve({\n baseUrl: `http://localhost:${port}`,\n protocol: 'http',\n port\n })\n \n // Consume response data to free up memory\n res.resume()\n })\n \n req.on('error', (err) => {\n debug('port-prober', `HTTP probe on port ${port} failed: ${err.message}`)\n resolve(null)\n })\n \n req.on('timeout', () => {\n debug('port-prober', `HTTP probe on port ${port} timed out`)\n req.destroy()\n resolve(null)\n })\n \n req.end()\n })\n}\n","/**\n * Connect client - client for Antigravity Connect API\n */\n\nimport https from 'https'\nimport http from 'http'\nimport { debug } from '../core/logger.js'\n\nexport interface ConnectUserStatus {\n // Basic status fields\n isAuthenticated?: boolean\n email?: string\n \n // Quota information (structure may vary based on actual API)\n quota?: {\n promptCredits?: {\n used?: number\n limit?: number\n remaining?: number\n }\n models?: Array<{\n modelId: string\n displayName?: string\n label?: string\n quota?: {\n remaining?: number\n limit?: number\n usedPercentage?: number\n remainingPercentage?: number\n resetTime?: string\n timeUntilResetMs?: number\n }\n isExhausted?: boolean\n }>\n }\n \n // Raw response for debugging\n raw?: unknown\n}\n\nexport interface ConnectModelInfo {\n modelId: string\n displayName?: string\n label?: string\n quota?: {\n remaining?: number\n limit?: number\n usedPercentage?: number\n remainingPercentage?: number\n resetTime?: string\n timeUntilResetMs?: number\n }\n isExhausted?: boolean\n}\n\nexport class ConnectClient {\n private baseUrl: string\n private csrfToken: string | undefined\n private isHttps: boolean\n \n constructor(baseUrl: string, csrfToken?: string) {\n this.baseUrl = baseUrl\n this.csrfToken = csrfToken\n this.isHttps = baseUrl.startsWith('https://')\n \n debug('connect-client', `Initialized with baseUrl: ${baseUrl}, hasToken: ${!!csrfToken}`)\n }\n \n /**\n * Get user status including quota information\n * Uses Connect RPC protocol to communicate with Antigravity language server\n */\n async getUserStatus(): Promise<ConnectUserStatus> {\n debug('connect-client', 'Fetching user status via Connect RPC')\n \n // Use the correct Connect RPC endpoint\n const endpoint = '/exa.language_server_pb.LanguageServerService/GetUserStatus'\n \n try {\n const response = await this.request('POST', endpoint, {\n metadata: {\n ideName: 'antigravity',\n extensionName: 'antigravity',\n locale: 'en'\n }\n })\n \n if (response) {\n debug('connect-client', `Got response from ${endpoint}`)\n return this.parseUserStatus(response)\n }\n } catch (err) {\n debug('connect-client', `Connect RPC call failed: ${err}`)\n throw new Error(`Failed to fetch user status: ${err instanceof Error ? err.message : 'Unknown error'}`)\n }\n \n throw new Error('Could not fetch user status from Connect RPC endpoint')\n }\n \n /**\n * Make an HTTP(S) request to the Connect API\n */\n private request(method: string, path: string, body?: unknown): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const url = new URL(path, this.baseUrl)\n \n const headers: Record<string, string> = {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n 'Connect-Protocol-Version': '1',\n }\n \n if (this.csrfToken) {\n // Use the correct CSRF header name for Antigravity Connect RPC\n headers['X-Codeium-Csrf-Token'] = this.csrfToken\n }\n \n const options = {\n hostname: url.hostname,\n port: url.port,\n path: url.pathname,\n method,\n headers,\n timeout: 5000,\n rejectUnauthorized: false, // Allow self-signed certificates\n }\n \n const protocol = this.isHttps ? https : http\n \n const req = protocol.request(options, (res) => {\n let data = ''\n \n res.on('data', (chunk) => {\n data += chunk\n })\n \n res.on('end', () => {\n if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {\n try {\n const parsed = JSON.parse(data)\n resolve(parsed)\n } catch {\n resolve(data)\n }\n } else if (res.statusCode === 404) {\n // Endpoint not found, try next\n reject(new Error(`Endpoint not found: ${path}`))\n } else {\n reject(new Error(`HTTP ${res.statusCode}: ${data}`))\n }\n })\n })\n \n req.on('error', (err) => {\n reject(err)\n })\n \n req.on('timeout', () => {\n req.destroy()\n reject(new Error('Request timed out'))\n })\n \n if (body) {\n req.write(JSON.stringify(body))\n }\n \n req.end()\n })\n }\n \n /**\n * Parse raw API response into ConnectUserStatus\n */\n private parseUserStatus(response: unknown): ConnectUserStatus {\n debug('connect-client', 'Raw response:', JSON.stringify(response, null, 2))\n \n const status: ConnectUserStatus = {\n raw: response\n }\n \n if (typeof response !== 'object' || response === null) {\n return status\n }\n \n const data = response as Record<string, unknown>\n \n // The actual response is nested under 'userStatus'\n const userStatus = (data.userStatus as Record<string, unknown>) || data\n \n // Extract email from userStatus\n if ('email' in userStatus && typeof userStatus.email === 'string') {\n status.email = userStatus.email\n }\n \n // Extract authentication status\n if ('isAuthenticated' in userStatus) {\n status.isAuthenticated = Boolean(userStatus.isAuthenticated)\n }\n \n // Extract quota from the nested structure\n status.quota = this.extractQuota(userStatus)\n \n return status\n }\n \n /**\n * Extract quota information from response\n */\n private extractQuota(data: Record<string, unknown>): ConnectUserStatus['quota'] {\n const quota: ConnectUserStatus['quota'] = {}\n \n // Extract prompt credits from planStatus structure\n const planStatus = data.planStatus as Record<string, unknown> | undefined\n if (planStatus) {\n const available = planStatus.availablePromptCredits\n const planInfo = planStatus.planInfo as Record<string, unknown> | undefined\n const monthly = planInfo?.monthlyPromptCredits\n \n if (typeof available === 'number' && typeof monthly === 'number') {\n const used = monthly - available\n quota.promptCredits = {\n used,\n limit: monthly,\n remaining: available\n }\n }\n }\n \n // Extract models from cascadeModelConfigData\n const cascadeData = data.cascadeModelConfigData as Record<string, unknown> | undefined\n const clientModelConfigs = cascadeData?.clientModelConfigs\n \n if (Array.isArray(clientModelConfigs)) {\n quota.models = clientModelConfigs.map(this.parseModel.bind(this))\n }\n \n return quota\n }\n \n /**\n * Parse a single model from the response\n */\n private parseModel(model: unknown): ConnectModelInfo {\n if (typeof model !== 'object' || model === null) {\n return {\n modelId: 'unknown',\n isExhausted: false\n }\n }\n \n const m = model as Record<string, unknown>\n \n // Extract model ID from modelOrAlias structure\n const modelOrAlias = m.modelOrAlias as Record<string, unknown> | undefined\n const modelId = typeof modelOrAlias?.model === 'string' ? modelOrAlias.model : 'unknown'\n \n // Extract quota info\n const quotaInfo = m.quotaInfo as Record<string, unknown> | undefined\n const remainingFraction = typeof quotaInfo?.remainingFraction === 'number' ? quotaInfo.remainingFraction : undefined\n const resetTime = typeof quotaInfo?.resetTime === 'string' ? quotaInfo.resetTime : undefined\n \n return {\n modelId,\n displayName: typeof m.label === 'string' ? m.label : undefined,\n label: typeof m.label === 'string' ? m.label : undefined,\n quota: {\n remaining: undefined,\n limit: undefined,\n usedPercentage: remainingFraction !== undefined ? (1 - remainingFraction) : undefined,\n remainingPercentage: remainingFraction,\n resetTime,\n timeUntilResetMs: resetTime ? this.parseResetTime(resetTime) : undefined,\n },\n isExhausted: remainingFraction === 0\n }\n }\n \n /**\n * Parse reset time to milliseconds until reset\n */\n private parseResetTime(resetTime: string): number | undefined {\n try {\n const resetDate = new Date(resetTime)\n const now = Date.now()\n const diff = resetDate.getTime() - now\n return diff > 0 ? diff : undefined\n } catch {\n return undefined\n }\n }\n}\n","/**\n * Local parser - converts Connect API response to QuotaSnapshot format\n */\n\nimport type { QuotaSnapshot, ModelQuotaInfo, PromptCreditsInfo } from '../quota/types.js'\nimport type { ConnectUserStatus } from './connect-client.js'\nimport { debug } from '../core/logger.js'\n\n/**\n * Parse Connect API user status into QuotaSnapshot format\n */\nexport function parseLocalQuotaSnapshot(userStatus: ConnectUserStatus): QuotaSnapshot {\n debug('local-parser', 'Parsing local user status into QuotaSnapshot')\n\n const snapshot: QuotaSnapshot = {\n timestamp: new Date().toISOString(),\n method: 'local',\n email: userStatus.email,\n models: []\n }\n\n // Parse prompt credits\n if (userStatus.quota?.promptCredits) {\n snapshot.promptCredits = parsePromptCredits(userStatus.quota.promptCredits)\n }\n\n // Parse models\n if (userStatus.quota?.models) {\n snapshot.models = userStatus.quota.models.map(parseModelQuota)\n }\n\n debug('local-parser', `Parsed ${snapshot.models.length} models`)\n return snapshot\n}\n\n/**\n * Parse prompt credits from Connect API format\n */\nfunction parsePromptCredits(credits: NonNullable<ConnectUserStatus['quota']>['promptCredits']): PromptCreditsInfo | undefined {\n if (!credits) {\n return undefined\n }\n\n const limit = credits.limit ?? 0\n const remaining = credits.remaining ?? limit\n const used = credits.used ?? (limit - remaining)\n\n if (limit === 0) {\n return undefined\n }\n\n const usedPercentage = limit > 0 ? used / limit : 0\n const remainingPercentage = limit > 0 ? remaining / limit : 1\n\n return {\n available: remaining,\n monthly: limit,\n usedPercentage,\n remainingPercentage\n }\n}\n\n/**\n * Parse a single model quota from Connect API format\n */\nfunction parseModelQuota(model: NonNullable<NonNullable<ConnectUserStatus['quota']>['models']>[number]): ModelQuotaInfo {\n const quota = model.quota\n\n return {\n label: model.label || model.displayName || model.modelId,\n modelId: model.modelId,\n remainingPercentage: quota?.remainingPercentage,\n isExhausted: model.isExhausted ?? (quota?.remainingPercentage === 0),\n resetTime: quota?.resetTime,\n timeUntilResetMs: quota?.timeUntilResetMs,\n isAutocompleteOnly: model.modelId.includes('gemini-2.5') ||\n (model.label || '').includes('Gemini 2.5') ||\n (model.displayName || '').includes('Gemini 2.5')\n }\n}\n","/**\n * Quota service - orchestrates fetching quota data\n */\n\nimport { debug } from '../core/logger.js'\nimport { getTokenManager } from '../google/token-manager.js'\nimport { CloudCodeClient, type FetchAvailableModelsResponse } from '../google/cloudcode.js'\nimport { parseQuotaSnapshot } from '../google/parser.js'\nimport { extractProjectId } from '../google/oauth.js'\nimport { \n detectAntigravityProcess, \n discoverPorts, \n probeForConnectAPI, \n ConnectClient, \n parseLocalQuotaSnapshot \n} from '../local/index.js'\nimport { \n AntigravityNotRunningError, \n LocalConnectionError, \n PortDetectionError,\n NoAuthMethodAvailableError\n} from '../core/errors.js'\nimport type { QuotaSnapshot } from './types.js'\n\nexport type QuotaMethod = 'google' | 'local' | 'auto'\n\n/**\n * Fetch quota using the specified method\n * @param method Method to use: 'auto' (default), 'google', or 'local'\n */\nexport async function fetchQuota(method: QuotaMethod = 'auto'): Promise<QuotaSnapshot> {\n if (method === 'auto') {\n try {\n debug('service', 'Auto mode: trying local method first')\n return await fetchQuotaLocal()\n } catch (err) {\n debug('service', 'Auto mode: local method failed', err)\n // Only fallback to Google if user is logged in\n const tokenManager = getTokenManager()\n if (tokenManager.isLoggedIn()) {\n debug('service', 'User is logged in, falling back to Google method')\n return fetchQuotaGoogle()\n }\n // User is not logged in and local failed - throw a helpful error\n throw new NoAuthMethodAvailableError()\n }\n }\n\n if (method === 'local') {\n return fetchQuotaLocal()\n }\n return fetchQuotaGoogle()\n}\n\n/**\n * Fetch quota from Google Cloud Code API\n */\nasync function fetchQuotaGoogle(): Promise<QuotaSnapshot> {\n debug('service', 'Fetching quota from Google')\n \n const tokenManager = getTokenManager()\n const email = tokenManager.getEmail()\n const client = new CloudCodeClient(tokenManager)\n \n // Fetch code assist (this one usually works)\n const codeAssistResponse = await client.loadCodeAssist()\n debug('service', 'Code assist response received', JSON.stringify(codeAssistResponse))\n \n // Save project ID to token storage for future use (for triggers, etc.)\n if (codeAssistResponse?.cloudaicompanionProject) {\n const projectId = extractProjectId(codeAssistResponse.cloudaicompanionProject)\n if (projectId) {\n tokenManager.setProjectId(projectId)\n debug('service', `Project ID saved: ${projectId}`)\n }\n }\n \n // Try to fetch models, but it might fail with 403\n let modelsResponse: FetchAvailableModelsResponse = {}\n try {\n modelsResponse = await client.fetchAvailableModels()\n debug('service', 'Models response received', JSON.stringify(modelsResponse))\n } catch (err) {\n debug('service', 'Failed to fetch models (might need different permissions)', err)\n // Continue without models - we'll still show prompt credits\n }\n \n // Parse into snapshot with email\n const snapshot = parseQuotaSnapshot(codeAssistResponse, modelsResponse, email)\n \n debug('service', 'Quota snapshot created')\n return snapshot\n}\n\n/**\n * Fetch quota from local Antigravity language server\n */\nasync function fetchQuotaLocal(): Promise<QuotaSnapshot> {\n debug('service', 'Fetching quota from local Antigravity server')\n \n // Step 1: Detect Antigravity process\n const processInfo = await detectAntigravityProcess()\n if (!processInfo) {\n throw new AntigravityNotRunningError()\n }\n \n debug('service', `Found Antigravity process: PID ${processInfo.pid}`)\n \n // Step 2: Discover all listening ports (to find the connect port, not extension_server_port)\n const ports = await discoverPorts(processInfo.pid)\n \n if (ports.length === 0) {\n throw new PortDetectionError()\n }\n \n debug('service', `Discovered ${ports.length} listening ports: ${ports.join(', ')}`)\n \n // Step 3: Probe ports to find Connect API (pass CSRF token for authentication)\n const probeResult = await probeForConnectAPI(ports, processInfo.csrfToken)\n if (!probeResult) {\n throw new LocalConnectionError('Could not find Antigravity Connect API on any port')\n }\n \n debug('service', `Found Connect API at ${probeResult.baseUrl}`)\n \n // Step 4: Connect to API and get user status\n const client = new ConnectClient(probeResult.baseUrl, processInfo.csrfToken)\n const userStatus = await client.getUserStatus()\n \n debug('service', 'User status received from local server')\n \n // Step 5: Parse into QuotaSnapshot\n const snapshot = parseLocalQuotaSnapshot(userStatus)\n \n debug('service', 'Local quota snapshot created')\n return snapshot\n}\n","/**\n * Quota output formatting\n */\n\nimport Table from 'cli-table3'\nimport type { QuotaSnapshot, ModelQuotaInfo } from './types.js'\n\n/**\n * Options for quota formatting\n */\nexport interface FormatOptions {\n allModels?: boolean\n}\n\n/**\n * Format milliseconds to human readable time\n */\nfunction formatTimeUntilReset(ms?: number): string {\n if (ms === undefined || ms <= 0) return 'N/A'\n\n const hours = Math.floor(ms / (1000 * 60 * 60))\n const minutes = Math.floor((ms % (1000 * 60 * 60)) / (1000 * 60))\n\n if (hours > 0) {\n return `${hours}h ${minutes}m`\n }\n return `${minutes}m`\n}\n\n/**\n * Format remaining percentage for display\n */\nfunction formatRemaining(model: ModelQuotaInfo): string {\n if (model.isExhausted) {\n return '❌ EXHAUSTED'\n }\n if (model.remainingPercentage === undefined) {\n return 'N/A'\n }\n\n const pct = Math.round(model.remainingPercentage * 100)\n if (pct >= 75) return `🟢 ${pct}%`\n if (pct >= 50) return `🟡 ${pct}%`\n if (pct >= 25) return `🟠 ${pct}%`\n return `🔴 ${pct}%`\n}\n\n/**\n * Print quota as a formatted table\n */\nexport function printQuotaTable(snapshot: QuotaSnapshot, options: FormatOptions = {}): void {\n const timestamp = new Date(snapshot.timestamp).toLocaleString()\n\n console.log()\n console.log(`📊 Antigravity Quota Status (via ${snapshot.method.toUpperCase()})`)\n console.log(` Retrieved: ${timestamp}`)\n\n // Display user info\n if (snapshot.email || snapshot.planType) {\n const userParts: string[] = []\n if (snapshot.email) {\n userParts.push(`👤 ${snapshot.email}`)\n }\n if (snapshot.planType) {\n userParts.push(`📋 Plan: ${snapshot.planType}`)\n }\n console.log(` ${userParts.join(' | ')}`)\n }\n\n const visibleModels = options.allModels\n ? snapshot.models\n : snapshot.models.filter(m => !m.isAutocompleteOnly)\n\n if (visibleModels.length > 0) {\n const table = new Table({\n head: ['Model', 'Remaining', 'Resets In'],\n style: {\n head: ['cyan'],\n border: ['gray']\n }\n })\n\n for (const model of visibleModels) {\n table.push([\n model.label,\n formatRemaining(model),\n formatTimeUntilReset(model.timeUntilResetMs)\n ])\n }\n\n console.log(table.toString())\n } else {\n console.log('No model quota information available.')\n if (!options.allModels && snapshot.models.some(m => m.isAutocompleteOnly)) {\n console.log('Tip: Use --all-models to see autocomplete models.')\n }\n }\n\n console.log()\n}\n\n/**\n * Print quota as JSON\n */\nexport function printQuotaJson(snapshot: QuotaSnapshot): void {\n console.log(JSON.stringify(snapshot, null, 2))\n}\n","/**\n * Table rendering utilities for multi-account displays\n */\n\nimport Table from 'cli-table3'\nimport type { AccountSummary } from '../accounts/types.js'\nimport type { QuotaSnapshot } from '../quota/types.js'\n\n/**\n * Format relative time (e.g., \"2 hours ago\")\n */\nfunction formatRelativeTime(isoDate: string | null): string {\n if (!isoDate) return 'Never'\n\n const date = new Date(isoDate)\n const now = Date.now()\n const diffMs = now - date.getTime()\n\n const minutes = Math.floor(diffMs / (1000 * 60))\n const hours = Math.floor(diffMs / (1000 * 60 * 60))\n const days = Math.floor(diffMs / (1000 * 60 * 60 * 24))\n\n if (minutes < 1) return 'Just now'\n if (minutes < 60) return `${minutes}m ago`\n if (hours < 24) return `${hours}h ago`\n if (days === 1) return 'Yesterday'\n return `${days} days ago`\n}\n\n/**\n * Format status icon\n */\nfunction formatStatus(status: string): string {\n switch (status) {\n case 'valid': return '✅'\n case 'expired': return '⚠️'\n case 'invalid': return '❌'\n default: return '❓'\n }\n}\n\n/**\n * Format credits display\n */\nfunction formatCredits(credits: { used: number; limit: number } | null | undefined): string {\n if (!credits) return '-'\n return `${credits.limit - credits.used} / ${credits.limit}`\n}\n\n/**\n * Render accounts list as a table\n */\nexport function renderAccountsTable(accounts: AccountSummary[]): void {\n if (accounts.length === 0) {\n console.log('\\n📭 No accounts found.')\n console.log('\\n💡 Run `antigravity-usage login` to add an account.\\n')\n return\n }\n\n console.log('\\n📊 Antigravity Accounts')\n console.log('═'.repeat(60))\n\n const totalWidth = process.stdout.columns || 80\n const isSmallTerminal = totalWidth < 90\n\n // Dynamic column widths\n // If small terminal, use tighter packing\n const colWidths = isSmallTerminal\n ? [25, 8, 12, 12] // Tighter widths for < 90 cols\n : [30, 10, 15, 15] // Standard widths\n\n // Ensure we don't exceed total width with borders (approx 10 chars)\n // If extremely small, let cli-table handle auto-sizing (pass undefined)\n const finalColWidths = totalWidth < 60 ? undefined : colWidths\n\n const tableOptions: any = {\n head: ['Account', 'Status', 'Credits', 'Last Used'],\n style: {\n head: ['cyan'],\n border: ['gray']\n }\n }\n\n if (finalColWidths) {\n tableOptions.colWidths = finalColWidths\n }\n\n const table = new Table(tableOptions)\n\n for (const account of accounts) {\n const nameDisplay = account.isActive\n ? `${account.email} [*]`\n : account.email\n\n table.push([\n nameDisplay,\n formatStatus(account.status),\n formatCredits(account.cachedCredits),\n formatRelativeTime(account.lastUsed)\n ])\n }\n\n console.log(table.toString())\n console.log('\\n[*] = active account\\n')\n}\n\n/**\n * Quota result for all accounts display\n */\nexport interface AllAccountsQuotaResult {\n email: string\n isActive: boolean\n status: 'success' | 'error' | 'cached'\n error?: string\n snapshot?: QuotaSnapshot\n cacheAge?: number\n}\n\n/**\n * Format quota remaining bar\n */\nfunction formatQuotaRemainingBar(remainingPercentage: number | undefined): string {\n const width = 10\n const filledChar = '█'\n const emptyChar = '░'\n\n if (remainingPercentage === undefined) {\n return `${emptyChar.repeat(width)} N/A`\n }\n\n const filled = Math.round((remainingPercentage / 100) * width)\n const empty = width - filled\n\n return `${filledChar.repeat(filled)}${emptyChar.repeat(empty)} ${Math.round(remainingPercentage)}%`\n}\n\n/**\n * Options for quota rendering\n */\nexport interface RenderOptions {\n allModels?: boolean\n}\n\n/**\n * Render quota for all accounts as a table\n */\nexport function renderAllQuotaTable(results: AllAccountsQuotaResult[], options: RenderOptions = {}): void {\n if (results.length === 0) {\n console.log('\\n📭 No accounts found.')\n console.log('\\n💡 Run `antigravity-usage login` to add an account.\\n')\n return\n }\n\n // Sort by quota remaining (highest to lowest)\n const sortedResults = [...results].sort((a, b) => {\n // Errors go last\n if (a.status === 'error' && b.status !== 'error') return 1\n if (a.status !== 'error' && b.status === 'error') return -1\n if (a.status === 'error' && b.status === 'error') return 0\n\n // Get remaining percentage for comparison\n const getRemaining = (result: AllAccountsQuotaResult): number => {\n // Filter out autocomplete models if requested\n const models = options.allModels\n ? result.snapshot?.models\n : result.snapshot?.models?.filter(m => !m.isAutocompleteOnly)\n\n const firstModel = models?.[0]\n if (!firstModel) return -1\n if (firstModel.isExhausted) return 0\n return firstModel.remainingPercentage ?? -1\n }\n\n const aRemaining = getRemaining(a)\n const bRemaining = getRemaining(b)\n\n // Sort descending (highest first)\n return bRemaining - aRemaining\n })\n\n console.log('\\n📊 Quota Overview - All Accounts')\n console.log('═'.repeat(70))\n\n const totalWidth = process.stdout.columns || 80\n\n // Calculate responsive widths\n // Standard: [30, 10, 15, 20] = ~75 content + 13 border = 88 chars\n\n let colWidths: number[] | undefined\n\n if (totalWidth < 80) {\n // Very small: auto-size or strict truncation\n colWidths = undefined\n } else if (totalWidth < 100) {\n // Compact mode\n colWidths = [25, 8, 12, 18]\n } else {\n // Spacious mode (fill remaining space with email column?)\n // For now keep standard spacious defaults\n colWidths = [30, 10, 15, 20]\n }\n\n const tableOptions: any = {\n head: ['Account', 'Source', 'Credits', 'Quota Remaining'],\n style: {\n head: ['cyan'],\n border: ['gray']\n }\n }\n\n if (colWidths) {\n tableOptions.colWidths = colWidths\n }\n\n const table = new Table(tableOptions)\n\n const errors: string[] = []\n\n for (const result of sortedResults) {\n const nameDisplay = result.isActive\n ? `${result.email} [*]`\n : result.email\n\n if (result.status === 'error') {\n table.push([\n nameDisplay,\n '-',\n '-',\n result.error || 'Error'\n ])\n errors.push(`${result.email}: ${result.error}`)\n } else {\n const snapshot = result.snapshot\n const source = result.status === 'cached'\n ? `Cached (${formatCacheAge(result.cacheAge)})`\n : (snapshot?.method.toUpperCase() || '-')\n\n // Get credits\n let credits = '-'\n if (snapshot?.promptCredits) {\n const pc = snapshot.promptCredits\n credits = `${pc.available} / ${pc.monthly}`\n }\n\n // Show the MINIMUM remaining percentage across relevant models\n // (This is the most constrained/concerning value for the user)\n let quotaRemaining = '-'\n const models = snapshot?.models || []\n const relevantModels = options.allModels\n ? models\n : models.filter(m => !m.isAutocompleteOnly)\n\n if (relevantModels.length > 0) {\n // Find minimum remaining percentage among relevant models\n const percentages = relevantModels\n .filter(m => m.remainingPercentage !== undefined)\n .map(m => m.remainingPercentage!)\n\n if (percentages.length > 0) {\n const minRemaining = Math.min(...percentages)\n quotaRemaining = formatQuotaRemainingBar(minRemaining * 100)\n } else if (relevantModels.some(m => m.isExhausted)) {\n quotaRemaining = '❌ EXHAUSTED'\n } else {\n quotaRemaining = formatQuotaRemainingBar(undefined)\n }\n }\n\n table.push([\n nameDisplay,\n source,\n credits,\n quotaRemaining\n ])\n }\n }\n\n console.log(table.toString())\n\n // Show errors if any\n if (errors.length > 0) {\n console.log(`\\n⚠️ ${errors.length} account(s) had errors:`)\n for (const err of errors) {\n console.log(` - ${err}`)\n }\n }\n\n console.log('\\n[*] = active account')\n console.log('💡 Use --refresh to fetch latest data\\n')\n}\n\nfunction formatCacheAge(seconds: number | undefined): string {\n if (seconds === undefined) return '?'\n if (seconds < 60) return `${seconds}s`\n if (seconds < 3600) return `${Math.floor(seconds / 60)}m`\n return `${Math.floor(seconds / 3600)}h`\n}\n","/**\n * Quota command - fetch and display quota information\n */\n\nimport { fetchQuota, type QuotaMethod } from '../quota/service.js'\nimport { printQuotaTable, printQuotaJson } from '../quota/format.js'\nimport { getTokenManager, getTokenManagerForAccount, resetTokenManager } from '../google/token-manager.js'\nimport { getAccountManager, saveCache, isCacheValid, loadCache, getCacheAge } from '../accounts/index.js'\nimport { renderAllQuotaTable, type AllAccountsQuotaResult } from '../render/index.js'\nimport { error as logError, debug, info } from '../core/logger.js'\nimport {\n NotLoggedInError,\n AuthenticationError,\n NetworkError,\n RateLimitError,\n APIError,\n AntigravityNotRunningError,\n LocalConnectionError,\n PortDetectionError,\n NoAuthMethodAvailableError\n} from '../core/errors.js'\n\ninterface QuotaOptions {\n json?: boolean\n method?: QuotaMethod\n all?: boolean\n account?: string\n refresh?: boolean\n allModels?: boolean\n}\n\n/**\n * Fetch quota for a single account\n */\nasync function fetchSingleAccountQuota(options: QuotaOptions): Promise<void> {\n // Determine which account to use\n const manager = getAccountManager()\n const accountEmail = options.account || manager.getActiveEmail()\n const originalActiveEmail = manager.getActiveEmail()\n\n // Force google method when --account is specified\n // (local method always uses IDE's logged-in account)\n let method = options.method || 'auto'\n if (options.account && method !== 'google') {\n debug('quota', `Account specified, forcing google method (local uses IDE account)`)\n method = 'google'\n }\n\n // Only check login for google method\n if (method === 'google') {\n const tokenManager = options.account\n ? getTokenManagerForAccount(options.account)\n : getTokenManager()\n\n if (!tokenManager.isLoggedIn()) {\n logError('Not logged in. Run: antigravity-usage login')\n process.exit(1)\n }\n }\n\n try {\n // Temporarily switch to the target account if needed\n let accountSwitched = false\n\n if (options.account && options.account !== originalActiveEmail) {\n debug('quota', `Temporarily switching to account ${options.account} for fetch`)\n manager.setActiveAccount(options.account)\n accountSwitched = true\n }\n\n try {\n debug('quota', `Fetching quota via ${method} method...`)\n const snapshot = await fetchQuota(method)\n\n // Cache the result if we have an account email\n if (accountEmail) {\n saveCache(accountEmail, snapshot)\n }\n\n if (options.json) {\n printQuotaJson(snapshot)\n } else {\n printQuotaTable(snapshot, { allModels: options.allModels })\n }\n } finally {\n // Always restore original active account\n if (accountSwitched && originalActiveEmail) {\n debug('quota', `Restoring active account to ${originalActiveEmail}`)\n manager.setActiveAccount(originalActiveEmail)\n }\n }\n } catch (err) {\n handleQuotaError(err)\n }\n}\n\n/**\n * Fetch quota for all accounts\n */\nasync function fetchAllAccountsQuota(options: QuotaOptions): Promise<void> {\n const manager = getAccountManager()\n const emails = manager.getAccountEmails()\n const activeEmail = manager.getActiveEmail()\n\n if (emails.length === 0) {\n logError('No accounts found. Run: antigravity-usage login')\n process.exit(1)\n }\n\n if (options.refresh) {\n info('🔄 Refreshing quota data for all accounts...\\n')\n }\n\n\n // IMPORTANT: Fetch sequentially, NOT in parallel\n // Parallel fetching causes race conditions with account switching\n const results: AllAccountsQuotaResult[] = []\n\n for (const email of emails) {\n const isActive = email === activeEmail\n\n try {\n // Check cache first (unless refresh requested)\n if (!options.refresh && isCacheValid(email)) {\n const cached = loadCache(email)\n if (cached) {\n debug('quota', `Using cached data for ${email}`)\n results.push({\n email,\n isActive,\n status: 'cached',\n snapshot: cached,\n cacheAge: getCacheAge(email) || 0\n })\n continue\n }\n }\n\n // Fetch fresh data\n debug('quota', `Fetching fresh data for ${email}`)\n\n const snapshot = await fetchQuotaForAccount(email, options.method || 'auto')\n\n // Cache the result\n saveCache(email, snapshot)\n\n results.push({\n email,\n isActive,\n status: 'success',\n snapshot\n })\n } catch (err) {\n debug('quota', `Error fetching quota for ${email}:`, err)\n\n // Try to use cached data on error\n const cached = loadCache(email)\n if (cached) {\n results.push({\n email,\n isActive,\n status: 'cached',\n snapshot: cached,\n cacheAge: getCacheAge(email) || 0\n })\n } else {\n results.push({\n email,\n isActive,\n status: 'error',\n error: err instanceof Error ? err.message : 'Unknown error'\n })\n }\n }\n }\n\n\n if (options.json) {\n console.log(JSON.stringify(results, null, 2))\n } else {\n renderAllQuotaTable(results, { allModels: options.allModels })\n }\n}\n\n/**\n * Fetch quota for a specific account\n */\nasync function fetchQuotaForAccount(email: string, method: QuotaMethod): Promise<any> {\n const manager = getAccountManager()\n const originalActiveEmail = manager.getActiveEmail()\n\n // CRITICAL: Local method always returns IDE's logged-in account data\n // We CANNOT use local method for non-IDE accounts in multi-account mode\n // Force Google API method to ensure we get the correct account's data\n let effectiveMethod = method\n\n if (method === 'auto' || method === 'local') {\n // Always use Google API for multi-account to avoid cache pollution\n effectiveMethod = 'google'\n debug('quota', `Forcing Google API for multi-account fetch (email: ${email})`)\n }\n\n // Temporarily switch to target account\n let accountSwitched = false\n if (email !== originalActiveEmail) {\n debug('quota', `Switching to ${email} for fetch`)\n manager.setActiveAccount(email)\n // CRITICAL: Reset TokenManager singleton so it loads the new account's tokens\n resetTokenManager()\n accountSwitched = true\n }\n\n try {\n const snapshot = await fetchQuota(effectiveMethod)\n return snapshot\n } finally {\n // Always restore original active account\n if (accountSwitched && originalActiveEmail) {\n debug('quota', `Restoring active account to ${originalActiveEmail}`)\n manager.setActiveAccount(originalActiveEmail)\n // Reset TokenManager again to pick up original account's tokens\n resetTokenManager()\n }\n }\n}\n\n/**\n * Handle quota errors\n */\nfunction handleQuotaError(err: unknown): never {\n // Auto mode: both methods unavailable\n if (err instanceof NoAuthMethodAvailableError) {\n logError(err.message)\n process.exit(1)\n }\n\n // Local method specific errors\n if (err instanceof AntigravityNotRunningError) {\n logError(err.message)\n console.log('\\nTip: Make sure Antigravity is running in your IDE (VSCode, etc.)')\n process.exit(1)\n }\n\n if (err instanceof LocalConnectionError) {\n logError(err.message)\n console.log('\\nTip: Try restarting your IDE or the Antigravity extension.')\n process.exit(1)\n }\n\n if (err instanceof PortDetectionError) {\n logError(err.message)\n console.log('\\nTip: This may happen if the Antigravity language server is still starting up.')\n process.exit(1)\n }\n\n // Google method specific errors\n if (err instanceof NotLoggedInError) {\n logError(err.message)\n process.exit(1)\n }\n\n if (err instanceof AuthenticationError) {\n logError(err.message)\n process.exit(1)\n }\n\n if (err instanceof NetworkError) {\n logError(err.message)\n process.exit(1)\n }\n\n if (err instanceof RateLimitError) {\n logError(err.message)\n if (err.retryAfterMs) {\n const seconds = Math.ceil(err.retryAfterMs / 1000)\n console.log(`Retry after ${seconds} seconds.`)\n }\n process.exit(1)\n }\n\n if (err instanceof APIError) {\n logError(err.message)\n process.exit(1)\n }\n\n // Unknown error\n logError(`Failed to fetch quota: ${err instanceof Error ? err.message : 'Unknown error'}`)\n debug('quota', 'Error details', err)\n process.exit(1)\n}\n\nexport async function quotaCommand(options: QuotaOptions): Promise<void> {\n if (options.all) {\n await fetchAllAccountsQuota(options)\n } else {\n await fetchSingleAccountQuota(options)\n }\n}\n","/**\n * Doctor command - diagnostics and troubleshooting\n */\n\nimport { getTokenManager } from '../google/token-manager.js'\nimport { getStorageInfo } from '../google/storage.js'\nimport { getConfigDir, getPlatform } from '../core/env.js'\nimport { maskEmail } from '../core/mask.js'\nimport { version } from '../version'\n\nexport function doctorCommand(): void {\n console.log()\n console.log('🩺 Antigravity Usage - Diagnostics')\n console.log('═'.repeat(50))\n console.log()\n \n // Version info\n console.log('📦 Version')\n console.log('─'.repeat(40))\n console.log(` CLI version: ${version}`)\n console.log(` Node.js: ${process.version}`)\n console.log(` Platform: ${getPlatform()}`)\n console.log()\n \n // Config paths\n const storage = getStorageInfo()\n console.log('📁 Configuration')\n console.log('─'.repeat(40))\n console.log(` Config dir: ${storage.configDir}`)\n console.log(` Tokens file: ${storage.tokensPath}`)\n console.log(` Tokens exist: ${storage.exists ? 'Yes' : 'No'}`)\n console.log()\n \n // Auth status\n const tokenManager = getTokenManager()\n console.log('🔐 Authentication')\n console.log('─'.repeat(40))\n \n if (!tokenManager.isLoggedIn()) {\n console.log(' Status: Not logged in')\n console.log()\n console.log(' 💡 Run `antigravity-usage login` to authenticate.')\n } else {\n console.log(' Status: Logged in')\n \n const email = tokenManager.getEmail()\n if (email) {\n console.log(` Email: ${maskEmail(email)}`)\n }\n \n const expiresAt = tokenManager.getExpiresAt()\n if (expiresAt) {\n const isExpired = tokenManager.isTokenExpired()\n console.log(` Token expires: ${expiresAt.toLocaleString()}`)\n console.log(` Token valid: ${isExpired ? 'No (needs refresh)' : 'Yes'}`)\n }\n }\n \n console.log()\n \n // Environment variables\n console.log('🔧 OAuth Configuration')\n console.log('─'.repeat(40))\n const hasClientId = !!process.env.ANTIGRAVITY_OAUTH_CLIENT_ID\n const hasClientSecret = !!process.env.ANTIGRAVITY_OAUTH_CLIENT_SECRET\n \n if (hasClientId || hasClientSecret) {\n console.log(' Using custom OAuth credentials:')\n console.log(` ANTIGRAVITY_OAUTH_CLIENT_ID: ${hasClientId ? 'Set' : 'Not set'}`)\n console.log(` ANTIGRAVITY_OAUTH_CLIENT_SECRET: ${hasClientSecret ? 'Set' : 'Not set'}`)\n } else {\n console.log(' ✅ Using built-in OAuth credentials')\n console.log(' 💡 Set ANTIGRAVITY_OAUTH_CLIENT_ID and ANTIGRAVITY_OAUTH_CLIENT_SECRET')\n console.log(' environment variables to use custom credentials.')\n }\n \n console.log()\n}\n","/**\n * Accounts command - manage multiple accounts\n */\n\nimport { getAccountManager } from '../accounts/index.js'\nimport { startOAuthFlow } from '../google/oauth.js'\nimport { getTokenManagerForAccount, resetTokenManager } from '../google/token-manager.js'\nimport { renderAccountsTable } from '../render/table.js'\nimport { success, warn, error as logError, info } from '../core/logger.js'\n\ninterface ListOptions {\n refresh?: boolean\n}\n\ninterface RemoveOptions {\n force?: boolean\n}\n\ninterface RefreshOptions {\n all?: boolean\n}\n\n/**\n * List all accounts\n */\nexport function listAccountsCommand(options: ListOptions): void {\n const manager = getAccountManager()\n const summaries = manager.getAccountSummaries()\n \n renderAccountsTable(summaries)\n \n if (options.refresh) {\n info('Use `antigravity-usage quota --all --refresh` to fetch fresh quota data.')\n }\n}\n\n/**\n * Add a new account (triggers OAuth flow)\n */\nexport async function addAccountCommand(): Promise<void> {\n info('Adding a new account...')\n \n const result = await startOAuthFlow()\n \n if (result.success) {\n success(`Account added successfully${result.email ? `: ${result.email}` : ''}!`)\n \n // Show updated account list\n const manager = getAccountManager()\n const summaries = manager.getAccountSummaries()\n console.log('\\nYour accounts:')\n renderAccountsTable(summaries)\n } else {\n logError(`Failed to add account: ${result.error}`)\n process.exit(1)\n }\n}\n\n/**\n * Switch active account\n */\nexport function switchAccountCommand(email: string): void {\n const manager = getAccountManager()\n \n // Check if account exists\n if (!manager.hasAccount(email)) {\n logError(`Account '${email}' not found.`)\n \n const emails = manager.getAccountEmails()\n if (emails.length > 0) {\n console.log('\\nAvailable accounts:')\n for (const e of emails) {\n console.log(` - ${e}`)\n }\n } else {\n info('\\nNo accounts found. Run `antigravity-usage login` to add one.')\n }\n \n process.exit(1)\n }\n \n // Switch account\n const switched = manager.setActiveAccount(email)\n \n if (switched) {\n success(`Switched to account: ${email}`)\n } else {\n logError(`Failed to switch to account: ${email}`)\n process.exit(1)\n }\n}\n\n/**\n * Remove an account\n */\nexport function removeAccountCommand(email: string, options: RemoveOptions): void {\n const manager = getAccountManager()\n \n // Check if account exists\n if (!manager.hasAccount(email)) {\n logError(`Account '${email}' not found.`)\n process.exit(1)\n }\n \n // Confirmation warning (unless --force)\n if (!options.force) {\n warn(`This will remove account '${email}' and all its data.`)\n info('Use --force to skip this warning.')\n // In a real CLI, we'd prompt for confirmation here\n // For now, just proceed\n }\n \n const removed = manager.removeAccount(email)\n \n if (removed) {\n success(`Account '${email}' removed.`)\n \n // Show remaining accounts\n const remaining = manager.getAccountEmails()\n if (remaining.length > 0) {\n const active = manager.getActiveEmail()\n console.log(`\\nActive account: ${active || 'none'}`)\n console.log(`Remaining accounts: ${remaining.length}`)\n } else {\n info('\\nNo accounts remaining. Run `antigravity-usage login` to add one.')\n }\n } else {\n logError(`Failed to remove account: ${email}`)\n process.exit(1)\n }\n}\n\n/**\n * Show current active account\n */\nexport function currentAccountCommand(): void {\n const manager = getAccountManager()\n const active = manager.getActiveEmail()\n \n if (active) {\n console.log()\n console.log(`📍 Active account: ${active}`)\n \n // Get account info\n const info = manager.getAccountInfo(active)\n if (info) {\n const statusIcon = info.status === 'valid' ? '✅' : \n info.status === 'expired' ? '⚠️' : '❌'\n console.log(` Status: ${statusIcon} ${info.status}`)\n \n if (info.tokens?.expiresAt) {\n const expiresAt = new Date(info.tokens.expiresAt).toLocaleString()\n console.log(` Token expires: ${expiresAt}`)\n }\n }\n console.log()\n } else {\n warn('No active account set.')\n \n const emails = manager.getAccountEmails()\n if (emails.length > 0) {\n console.log('\\nAvailable accounts:')\n for (const e of emails) {\n console.log(` - ${e}`)\n }\n info('\\nRun `antigravity-usage accounts switch <email>` to set an active account.')\n } else {\n info('\\nRun `antigravity-usage login` to add an account.')\n }\n }\n}\n\n/**\n * Refresh account tokens\n */\nexport async function refreshAccountCommand(email: string | undefined, options: RefreshOptions): Promise<void> {\n const manager = getAccountManager()\n \n // Refresh all accounts\n if (options.all) {\n const emails = manager.getAccountEmails()\n \n if (emails.length === 0) {\n warn('No accounts to refresh.')\n return\n }\n \n console.log(`\\n🔄 Refreshing ${emails.length} account(s)...\\n`)\n \n let successCount = 0\n let failCount = 0\n \n for (const e of emails) {\n try {\n const tokenManager = getTokenManagerForAccount(e)\n if (tokenManager.isTokenExpired()) {\n await tokenManager.refreshToken()\n success(` ✅ ${e}`)\n successCount++\n } else {\n info(` ⏭️ ${e} (token still valid)`)\n successCount++\n }\n } catch (err) {\n logError(` ❌ ${e}: ${err instanceof Error ? err.message : 'Failed'}`)\n failCount++\n }\n }\n \n resetTokenManager()\n \n console.log()\n if (failCount > 0) {\n warn(`${failCount} account(s) need re-authentication. Run: antigravity-usage login`)\n } else {\n success(`All ${successCount} account(s) refreshed successfully!`)\n }\n return\n }\n \n // Refresh specific or active account\n const targetEmail = email || manager.getActiveEmail()\n \n if (!targetEmail) {\n logError('No account specified and no active account.')\n info('Usage: antigravity-usage accounts refresh <email>')\n info(' or: antigravity-usage accounts refresh --all')\n process.exit(1)\n }\n \n if (!manager.hasAccount(targetEmail)) {\n logError(`Account '${targetEmail}' not found.`)\n process.exit(1)\n }\n \n console.log(`\\n🔄 Refreshing ${targetEmail}...`)\n \n try {\n const tokenManager = getTokenManagerForAccount(targetEmail)\n \n if (!tokenManager.isTokenExpired()) {\n info(`Token for ${targetEmail} is still valid.`)\n return\n }\n \n await tokenManager.refreshToken()\n resetTokenManager()\n success(`\\n✅ Token refreshed for ${targetEmail}`)\n } catch (err) {\n logError(`\\n❌ Failed to refresh token: ${err instanceof Error ? err.message : 'Unknown error'}`)\n info('\\nThe refresh token may be expired. Please re-authenticate:')\n info(` antigravity-usage accounts switch ${targetEmail}`)\n info(' antigravity-usage login')\n process.exit(1)\n }\n}\n\n/**\n * Main accounts command handler - dispatches to subcommands\n */\nexport async function accountsCommand(\n subcommand: string,\n args: string[],\n options: { refresh?: boolean; force?: boolean; all?: boolean }\n): Promise<void> {\n switch (subcommand) {\n case 'list':\n listAccountsCommand({ refresh: options.refresh })\n break\n \n case 'add':\n await addAccountCommand()\n break\n \n case 'switch':\n if (!args[0]) {\n logError('Please specify an account email to switch to.')\n console.log('Usage: antigravity-usage accounts switch <email>')\n process.exit(1)\n }\n switchAccountCommand(args[0])\n break\n \n case 'remove':\n if (!args[0]) {\n logError('Please specify an account email to remove.')\n console.log('Usage: antigravity-usage accounts remove <email>')\n process.exit(1)\n }\n removeAccountCommand(args[0], { force: options.force })\n break\n \n case 'current':\n currentAccountCommand()\n break\n \n case 'refresh':\n await refreshAccountCommand(args[0], { all: options.all })\n break\n \n default:\n // Default to list if no subcommand\n listAccountsCommand({ refresh: options.refresh })\n }\n}\n","/**\n * Wakeup command - Auto wake-up and warm up AI models\n */\n\nimport inquirer from 'inquirer'\nimport Table from 'cli-table3'\nimport {\n loadWakeupConfig,\n saveWakeupConfig,\n getOrCreateConfig,\n getRecentHistory,\n getLastTrigger,\n clearTriggerHistory,\n type WakeupConfig,\n type TriggerRecord,\n getDefaultConfig\n} from '../wakeup/index.js'\nimport {\n installCronJob,\n uninstallCronJob,\n getCronStatus,\n isCronSupported\n} from '../wakeup/cron-installer.js'\nimport {\n configToCronExpression,\n getScheduleDescription,\n getNextRunEstimate\n} from '../wakeup/schedule-converter.js'\nimport {\n executeTrigger,\n testTrigger\n} from '../wakeup/trigger-service.js'\nimport {\n resolveAccounts,\n getAccountResolutionStatus\n} from '../wakeup/account-resolver.js'\nimport { getAccountManager } from '../accounts/manager.js'\nimport { debug } from '../core/logger.js'\n\n// Subcommand type\ntype WakeupSubcommand = 'config' | 'trigger' | 'install' | 'uninstall' | 'test' | 'history' | 'status'\n\ninterface WakeupOptions {\n scheduled?: boolean\n limit?: string\n json?: boolean\n}\n\n/**\n * Main wakeup command handler\n */\nexport async function wakeupCommand(\n subcommand: WakeupSubcommand,\n args: string[],\n options: WakeupOptions\n): Promise<void> {\n debug('wakeup', `Subcommand: ${subcommand}, options:`, options)\n \n switch (subcommand) {\n case 'config':\n await configureWakeup()\n break\n \n case 'trigger':\n await runScheduledTrigger(options.scheduled ?? false)\n break\n \n case 'install':\n await installSchedule()\n break\n \n case 'uninstall':\n await uninstallSchedule()\n break\n \n case 'test':\n await runTestTrigger()\n break\n \n case 'history':\n await showHistory(options)\n break\n \n case 'status':\n default:\n await showStatus()\n break\n }\n}\n\n// ============================================================================\n// Subcommand Implementations\n// ============================================================================\n\n/**\n * Configure wake-up schedule interactively\n */\nasync function configureWakeup(): Promise<void> {\n console.log('\\n🔧 Auto Wake-up Configuration\\n')\n \n const config = getOrCreateConfig()\n const accountManager = getAccountManager()\n const accounts = accountManager.getAccountEmails()\n \n if (accounts.length === 0) {\n console.log('❌ No accounts available. Please login first:')\n console.log(' antigravity-usage login\\n')\n return\n }\n \n // Step 1: Enable/disable\n const { enabled } = await inquirer.prompt([{\n type: 'confirm',\n name: 'enabled',\n message: 'Enable auto wake-up?',\n default: config.enabled\n }])\n \n if (!enabled) {\n config.enabled = false\n saveWakeupConfig(config)\n console.log('\\n✅ Auto wake-up disabled')\n return\n }\n \n // Step 2: Choose trigger mode\n const { triggerMode } = await inquirer.prompt([{\n type: 'list',\n name: 'triggerMode',\n message: 'Trigger mode:',\n choices: [\n { name: 'Schedule-based (run at specific times)', value: 'schedule' },\n { name: 'Quota-reset-based (trigger when quota resets)', value: 'reset' }\n ],\n default: config.wakeOnReset ? 'reset' : 'schedule'\n }])\n \n config.wakeOnReset = triggerMode === 'reset'\n \n // Step 3: Configure schedule (if schedule mode)\n if (!config.wakeOnReset) {\n const { scheduleMode } = await inquirer.prompt([{\n type: 'list',\n name: 'scheduleMode',\n message: 'Schedule type:',\n choices: [\n { name: 'Every N hours', value: 'interval' },\n { name: 'Daily at specific times', value: 'daily' },\n { name: 'Custom cron expression', value: 'custom' }\n ],\n default: config.scheduleMode\n }])\n \n config.scheduleMode = scheduleMode\n \n if (scheduleMode === 'interval') {\n const { intervalHours } = await inquirer.prompt([{\n type: 'number',\n name: 'intervalHours',\n message: 'Trigger every N hours:',\n default: config.intervalHours || 6,\n validate: (val: number) => val >= 1 && val <= 23 ? true : 'Must be 1-23'\n }])\n config.intervalHours = intervalHours\n } else if (scheduleMode === 'daily') {\n const { dailyTime } = await inquirer.prompt([{\n type: 'input',\n name: 'dailyTime',\n message: 'Time to trigger (HH:MM):',\n default: config.dailyTimes?.[0] || '09:00',\n validate: (val: string) => /^\\d{1,2}:\\d{2}$/.test(val) ? true : 'Use HH:MM format'\n }])\n config.dailyTimes = [dailyTime]\n } else if (scheduleMode === 'custom') {\n const { cronExpression } = await inquirer.prompt([{\n type: 'input',\n name: 'cronExpression',\n message: 'Cron expression (min hour day month weekday):',\n default: config.cronExpression || '0 */6 * * *'\n }])\n config.cronExpression = cronExpression\n }\n } else {\n // Reset mode configuration\n const { resetCooldown } = await inquirer.prompt([{\n type: 'number',\n name: 'resetCooldown',\n message: 'Cooldown between triggers (minutes):',\n default: config.resetCooldownMinutes || 10,\n validate: (val: number) => val >= 1 ? true : 'Must be at least 1 minute'\n }])\n config.resetCooldownMinutes = resetCooldown\n }\n \n // Step 4: Models - Use default models that cover both families\n // claude-sonnet-4-5 triggers Claude family\n // gemini-3-flash and gemini-3-pro-low trigger both Gemini quota groups\n config.selectedModels = ['claude-sonnet-4-5', 'gemini-3-flash', 'gemini-3-pro-low']\n console.log('\\n 📦 Models: claude-sonnet-4-5, gemini-3-flash, gemini-3-pro-low')\n console.log(' (Triggers both Claude and Gemini families)')\n \n // Step 5: Select accounts\n if (accounts.length > 1) {\n const { selectedAccounts } = await inquirer.prompt([{\n type: 'checkbox',\n name: 'selectedAccounts',\n message: 'Select accounts to use:',\n choices: accounts.map(email => ({\n name: email,\n value: email,\n checked: !config.selectedAccounts || config.selectedAccounts.includes(email)\n }))\n }])\n config.selectedAccounts = selectedAccounts.length > 0 ? selectedAccounts : undefined\n } else {\n config.selectedAccounts = undefined // Use default (active account)\n }\n \n // Step 6: Custom prompt (optional)\n const { customPrompt } = await inquirer.prompt([{\n type: 'input',\n name: 'customPrompt',\n message: 'Custom wake-up prompt (leave empty for default \"hi\"):',\n default: config.customPrompt || ''\n }])\n config.customPrompt = customPrompt || undefined\n \n // Step 7: Max output tokens\n const { maxTokens } = await inquirer.prompt([{\n type: 'number',\n name: 'maxTokens',\n message: 'Max output tokens (0 = no limit):',\n default: config.maxOutputTokens || 0\n }])\n config.maxOutputTokens = maxTokens\n \n // Save config\n config.enabled = true\n saveWakeupConfig(config)\n \n console.log('\\n✅ Configuration saved!')\n console.log(` Mode: ${getScheduleDescription(config)}`)\n console.log(` Models: ${config.selectedModels.join(', ')}`)\n console.log(` Accounts: ${config.selectedAccounts?.join(', ') || 'Active account'}`)\n \n // Offer to install cron job if schedule mode\n if (!config.wakeOnReset && isCronSupported()) {\n const { installNow } = await inquirer.prompt([{\n type: 'confirm',\n name: 'installNow',\n message: 'Install to system cron now?',\n default: true\n }])\n \n if (installNow) {\n await installSchedule()\n } else {\n console.log('\\n📋 To install later, run:')\n console.log(' antigravity-usage wakeup install')\n }\n }\n \n console.log('')\n}\n\n/**\n * Run a scheduled trigger (called by cron)\n */\nasync function runScheduledTrigger(isScheduled: boolean): Promise<void> {\n debug('wakeup', `Running trigger (scheduled: ${isScheduled})`)\n \n const config = loadWakeupConfig()\n \n if (!config || !config.enabled) {\n debug('wakeup', 'Wakeup not configured or disabled')\n return\n }\n \n const accounts = resolveAccounts(config.selectedAccounts)\n if (accounts.length === 0) {\n debug('wakeup', 'No valid accounts')\n return\n }\n \n if (config.selectedModels.length === 0) {\n debug('wakeup', 'No models selected')\n return\n }\n \n // Execute trigger for each account\n for (const accountEmail of accounts) {\n const result = await executeTrigger({\n models: config.selectedModels,\n accountEmail,\n triggerType: 'auto',\n triggerSource: isScheduled ? 'scheduled' : 'manual',\n customPrompt: config.customPrompt,\n maxOutputTokens: config.maxOutputTokens\n })\n \n const successCount = result.results.filter(r => r.success).length\n console.log(`[${new Date().toISOString()}] ${accountEmail}: ${successCount}/${result.results.length} models triggered`)\n }\n}\n\n/**\n * Install schedule to system cron\n */\nasync function installSchedule(): Promise<void> {\n console.log('\\n📅 Installing wake-up schedule to cron...\\n')\n \n if (!isCronSupported()) {\n console.log('❌ Cron is not supported on this platform.')\n console.log(' Windows Task Scheduler support coming soon.')\n return\n }\n \n const config = loadWakeupConfig()\n \n if (!config) {\n console.log('❌ No wake-up configuration found.')\n console.log(' Run: antigravity-usage wakeup config')\n return\n }\n \n if (!config.enabled) {\n console.log('❌ Wake-up is disabled. Enable it first:')\n console.log(' antigravity-usage wakeup config')\n return\n }\n \n if (config.wakeOnReset) {\n console.log('ℹ️ Quota-reset mode does not require cron installation.')\n console.log(' Triggers happen automatically when you check quota.')\n return\n }\n \n try {\n const cronExpression = configToCronExpression(config)\n console.log(` Schedule: ${getScheduleDescription(config)}`)\n console.log(` Cron: ${cronExpression}`)\n console.log('')\n \n const result = await installCronJob(cronExpression)\n \n if (result.success) {\n console.log('✅ Cron job installed successfully!')\n console.log(` Next run: ${getNextRunEstimate(cronExpression)}`)\n console.log('')\n console.log(' To check status: antigravity-usage wakeup status')\n console.log(' To uninstall: antigravity-usage wakeup uninstall')\n } else {\n console.log('⚠️ Automatic installation failed.')\n if (result.manualInstructions) {\n console.log('')\n console.log(result.manualInstructions)\n }\n }\n } catch (err) {\n console.log(`❌ Error: ${err instanceof Error ? err.message : err}`)\n }\n \n console.log('')\n}\n\n/**\n * Uninstall schedule from system cron\n */\nasync function uninstallSchedule(): Promise<void> {\n console.log('\\n🗑️ Removing wake-up schedule from cron...\\n')\n \n const success = await uninstallCronJob()\n \n if (success) {\n console.log('✅ Cron job removed successfully!')\n } else {\n console.log('⚠️ Could not remove cron job. It may not be installed.')\n console.log(' Check your crontab: crontab -l')\n }\n \n console.log('')\n}\n\n/**\n * Run a manual test trigger\n */\nasync function runTestTrigger(): Promise<void> {\n console.log('\\n🧪 Test Trigger\\n')\n \n const accountManager = getAccountManager()\n const accounts = accountManager.getAccountEmails()\n \n if (accounts.length === 0) {\n console.log('❌ No accounts available. Please login first.')\n return\n }\n \n // Select account\n let accountEmail = accounts[0]\n if (accounts.length > 1) {\n const { selectedAccount } = await inquirer.prompt([{\n type: 'list',\n name: 'selectedAccount',\n message: 'Select account:',\n choices: accounts\n }])\n accountEmail = selectedAccount\n }\n \n // Enter model ID\n const config = loadWakeupConfig()\n const { modelId } = await inquirer.prompt([{\n type: 'input',\n name: 'modelId',\n message: 'Model ID to test:',\n default: config?.selectedModels[0] || 'claude-sonnet-4-5'\n }])\n \n // Enter prompt\n const { prompt } = await inquirer.prompt([{\n type: 'input',\n name: 'prompt',\n message: 'Test prompt:',\n default: 'hi'\n }])\n \n console.log('\\n⏳ Triggering...')\n \n try {\n const result = await testTrigger(modelId, accountEmail, prompt)\n \n if (result.success) {\n console.log(`\\n✅ Success! (${result.durationMs}ms)`)\n if (result.response) {\n console.log(`\\n📝 Response:\\n${result.response.substring(0, 200)}...`)\n }\n if (result.tokensUsed) {\n console.log(`\\n📊 Tokens: ${result.tokensUsed.total} (prompt: ${result.tokensUsed.prompt}, completion: ${result.tokensUsed.completion})`)\n }\n } else {\n console.log(`\\n❌ Failed: ${result.error}`)\n }\n } catch (err) {\n console.log(`\\n❌ Error: ${err instanceof Error ? err.message : err}`)\n }\n \n console.log('')\n \n // Exit cleanly to avoid hanging on open HTTP connections\n process.exit(0)\n}\n\n/**\n * Show trigger history\n */\nasync function showHistory(options: WakeupOptions): Promise<void> {\n const limit = parseInt(options.limit || '10', 10)\n const history = getRecentHistory(limit)\n \n if (history.length === 0) {\n console.log('\\n📜 No trigger history yet.\\n')\n return\n }\n \n if (options.json) {\n console.log(JSON.stringify(history, null, 2))\n return\n }\n \n console.log(`\\n📜 Trigger History (last ${Math.min(limit, history.length)} records)\\n`)\n \n const table = new Table({\n head: ['Time', 'Source', 'Model', 'Account', 'Duration', 'Status'],\n style: { head: ['cyan'] }\n })\n \n for (const record of history) {\n const time = new Date(record.timestamp).toLocaleString()\n const status = record.success ? '✅' : `❌ ${record.error?.substring(0, 20) || ''}`\n \n table.push([\n time,\n record.triggerSource,\n record.models[0] || '-',\n record.accountEmail.split('@')[0],\n `${record.durationMs}ms`,\n status\n ])\n }\n \n console.log(table.toString())\n console.log('')\n}\n\n/**\n * Show current wake-up status\n */\nasync function showStatus(): Promise<void> {\n console.log('\\n📊 Auto Wake-up Status\\n')\n \n const config = loadWakeupConfig()\n \n if (!config) {\n console.log(' Status: Not configured')\n console.log('')\n console.log(' To configure: antigravity-usage wakeup config')\n console.log('')\n return\n }\n \n // Basic status\n console.log(` Enabled: ${config.enabled ? '✅ Yes' : '❌ No'}`)\n console.log(` Mode: ${getScheduleDescription(config)}`)\n \n // Models\n if (config.selectedModels.length > 0) {\n console.log(` Models: ${config.selectedModels.join(', ')}`)\n } else {\n console.log(' Models: None selected')\n }\n \n // Accounts\n console.log(` Accounts: ${getAccountResolutionStatus(config.selectedAccounts)}`)\n \n // Cron status (for schedule mode)\n if (!config.wakeOnReset && config.enabled) {\n const cronStatus = await getCronStatus()\n if (cronStatus.installed) {\n console.log(` Cron: ✅ Installed (${cronStatus.cronExpression})`)\n if (cronStatus.nextRun) {\n console.log(` Next run: ${cronStatus.nextRun}`)\n }\n } else {\n console.log(' Cron: ❌ Not installed')\n console.log(' Run: antigravity-usage wakeup install')\n }\n }\n \n // Last trigger\n const lastTrigger = getLastTrigger()\n if (lastTrigger) {\n const ago = getTimeAgo(new Date(lastTrigger.timestamp))\n const status = lastTrigger.success ? '✅ success' : `❌ ${lastTrigger.error?.substring(0, 30) || 'failed'}`\n console.log(` Last trigger: ${ago} (${status})`)\n } else {\n console.log(' Last trigger: Never')\n }\n \n console.log('')\n}\n\n/**\n * Get human-readable time ago string\n */\nfunction getTimeAgo(date: Date): string {\n const seconds = Math.floor((Date.now() - date.getTime()) / 1000)\n \n if (seconds < 60) return 'Just now'\n if (seconds < 3600) return `${Math.floor(seconds / 60)} minutes ago`\n if (seconds < 86400) return `${Math.floor(seconds / 3600)} hours ago`\n return `${Math.floor(seconds / 86400)} days ago`\n}\n","/**\n * Auto Wake-up types\n * Types for schedule configuration, trigger history, and reset state\n */\n\n// ============================================================================\n// Schedule Configuration\n// ============================================================================\n\n/**\n * Main wake-up configuration\n */\nexport interface WakeupConfig {\n // Global settings\n enabled: boolean\n selectedModels: string[] // Model IDs to trigger\n selectedAccounts?: string[] // Account emails (undefined = use active)\n customPrompt?: string // Optional custom wake-up prompt\n maxOutputTokens: number // 0 = no limit\n \n // Schedule-based mode\n scheduleMode: ScheduleMode\n intervalHours?: number // For interval mode (e.g., 6 = every 6 hours)\n dailyTimes?: string[] // For daily mode: [\"09:00\", \"17:00\"]\n weeklySchedule?: WeeklySchedule // For weekly mode\n cronExpression?: string // For custom mode (advanced users)\n \n // Quota-reset mode\n wakeOnReset: boolean // Enable quota-reset-based triggering\n resetCooldownMinutes: number // Cooldown between reset triggers (default: 10)\n}\n\n/**\n * Weekly schedule - maps day number to array of times\n * Day numbers: 0=Sunday, 1=Monday, ..., 6=Saturday\n */\nexport interface WeeklySchedule {\n [day: number]: string[]\n}\n\n/**\n * Schedule mode types\n */\nexport type ScheduleMode = 'interval' | 'daily' | 'weekly' | 'custom'\n\n/**\n * Default configuration\n * \n * Default models trigger both Claude and Gemini families:\n * - claude-sonnet-4-5: Wakes up Claude family\n * - gemini-3-flash: Wakes up Gemini flash quota group\n * - gemini-3-pro-low: Wakes up Gemini pro quota group\n */\nexport function getDefaultConfig(): WakeupConfig {\n return {\n enabled: false,\n selectedModels: ['claude-sonnet-4-5', 'gemini-3-flash', 'gemini-3-pro-low'],\n selectedAccounts: undefined,\n customPrompt: undefined,\n maxOutputTokens: 1, // Minimal tokens to save quota\n scheduleMode: 'interval',\n intervalHours: 6,\n dailyTimes: ['09:00'],\n weeklySchedule: {},\n cronExpression: undefined,\n wakeOnReset: false,\n resetCooldownMinutes: 10\n }\n}\n\n// ============================================================================\n// Trigger History\n// ============================================================================\n\n/**\n * Trigger type - manual (user initiated) or auto (scheduled/reset-based)\n */\nexport type TriggerType = 'manual' | 'auto'\n\n/**\n * Trigger source - how the trigger was initiated\n */\nexport type TriggerSource = 'manual' | 'scheduled' | 'quota_reset'\n\n/**\n * Token usage information from API response\n */\nexport interface TokenUsage {\n prompt: number\n completion: number\n total: number\n}\n\n/**\n * Single trigger history record\n */\nexport interface TriggerRecord {\n timestamp: string // ISO timestamp\n success: boolean\n triggerType: TriggerType\n triggerSource: TriggerSource\n models: string[] // Model IDs triggered\n accountEmail: string\n durationMs: number\n prompt: string // Actual prompt used\n response?: string // AI response (truncated to 500 chars)\n error?: string // Error message if failed\n tokensUsed?: TokenUsage\n}\n\n// ============================================================================\n// Reset Detection State\n// ============================================================================\n\n/**\n * State for a single model's reset tracking\n */\nexport interface ModelResetState {\n lastResetAt: string // Last resetAt timestamp we triggered for\n lastTriggeredTime: string // When we last triggered (ISO timestamp)\n}\n\n/**\n * Reset deduplication state - keyed by model reset key\n * Key is modelConstant if available, otherwise modelId\n */\nexport interface ResetState {\n [modelResetKey: string]: ModelResetState\n}\n\n// ============================================================================\n// Model Mapping\n// ============================================================================\n\n/**\n * Mapping from model ID to model constant\n * Used for quota reset deduplication\n */\nexport interface ModelMapping {\n [modelId: string]: string\n}\n\n// ============================================================================\n// Trigger Service Types\n// ============================================================================\n\n/**\n * Options for executing a trigger\n */\nexport interface TriggerOptions {\n models: string[] // Model IDs to trigger\n accountEmail: string // Which account to use\n triggerType: TriggerType\n triggerSource: TriggerSource\n customPrompt?: string\n maxOutputTokens?: number // 0 = no limit\n}\n\n/**\n * Result from triggering a single model\n */\nexport interface ModelTriggerResult {\n modelId: string\n success: boolean\n durationMs: number\n response?: string\n error?: string\n tokensUsed?: TokenUsage\n}\n\n/**\n * Overall trigger execution result\n */\nexport interface TriggerResult {\n success: boolean // True if all models succeeded\n results: ModelTriggerResult[]\n}\n\n// ============================================================================\n// Cron Installer Types\n// ============================================================================\n\n/**\n * Result from cron installation attempt\n */\nexport interface CronInstallResult {\n success: boolean\n cronExpression?: string\n manualInstructions?: string // Fallback instructions if auto-install fails\n error?: string\n}\n\n/**\n * Status of cron installation\n */\nexport interface CronStatus {\n installed: boolean\n cronExpression?: string\n nextRun?: string // Human-readable next run time\n}\n\n// ============================================================================\n// Reset Detection Types\n// ============================================================================\n\n/**\n * Result from reset detection\n */\nexport interface DetectionResult {\n triggered: boolean\n triggeredModels: string[]\n}\n","/**\n * Auto Wake-up storage service\n * Handles persistence of config, trigger history, reset state, and model mappings\n */\n\nimport { join } from 'path'\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'\nimport { debug } from '../core/logger.js'\nimport { getConfigDir } from '../core/env.js'\nimport type { \n WakeupConfig, \n TriggerRecord, \n ResetState,\n ModelMapping \n} from './types.js'\nimport { getDefaultConfig } from './types.js'\n\n// Storage paths\nconst WAKEUP_DIR_NAME = 'wakeup'\nconst CONFIG_FILE_NAME = 'config.json'\nconst HISTORY_FILE_NAME = 'history.json'\nconst RESET_STATE_FILE_NAME = 'reset-state.json'\nconst MODEL_MAPPING_FILE_NAME = 'model-mapping.json'\n\n// History ring buffer size\nconst MAX_HISTORY_ENTRIES = 100\n\n/**\n * Get wakeup storage directory path\n */\nfunction getWakeupDir(): string {\n return join(getConfigDir(), WAKEUP_DIR_NAME)\n}\n\n/**\n * Ensure wakeup directory exists\n */\nfunction ensureWakeupDir(): void {\n const dir = getWakeupDir()\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n debug('wakeup-storage', `Created wakeup directory: ${dir}`)\n }\n}\n\n/**\n * Generic JSON file reader\n */\nfunction readJsonFile<T>(filename: string, defaultValue: T): T {\n const filepath = join(getWakeupDir(), filename)\n try {\n if (existsSync(filepath)) {\n const content = readFileSync(filepath, 'utf-8')\n return JSON.parse(content) as T\n }\n } catch (err) {\n debug('wakeup-storage', `Error reading ${filename}:`, err)\n }\n return defaultValue\n}\n\n/**\n * Generic JSON file writer\n */\nfunction writeJsonFile<T>(filename: string, data: T): void {\n ensureWakeupDir()\n const filepath = join(getWakeupDir(), filename)\n try {\n writeFileSync(filepath, JSON.stringify(data, null, 2), 'utf-8')\n debug('wakeup-storage', `Wrote ${filename}`)\n } catch (err) {\n debug('wakeup-storage', `Error writing ${filename}:`, err)\n throw err\n }\n}\n\n// ============================================================================\n// Config Operations\n// ============================================================================\n\n/**\n * Load wake-up configuration\n * Returns null if no config exists\n */\nexport function loadWakeupConfig(): WakeupConfig | null {\n const config = readJsonFile<WakeupConfig | null>(CONFIG_FILE_NAME, null)\n if (config) {\n debug('wakeup-storage', 'Loaded wakeup config')\n }\n return config\n}\n\n/**\n * Save wake-up configuration\n */\nexport function saveWakeupConfig(config: WakeupConfig): void {\n writeJsonFile(CONFIG_FILE_NAME, config)\n debug('wakeup-storage', 'Saved wakeup config')\n}\n\n/**\n * Get or create default config\n * Includes migration logic to update existing configs to new default models\n */\nexport function getOrCreateConfig(): WakeupConfig {\n const existing = loadWakeupConfig()\n if (existing) {\n // Auto-migrate to new default models if selectedModels is empty\n // This ensures both Claude and Gemini families (both quota groups) are triggered\n if (!existing.selectedModels || existing.selectedModels.length === 0) {\n existing.selectedModels = ['claude-sonnet-4-5', 'gemini-3-flash', 'gemini-3-pro-low']\n saveWakeupConfig(existing)\n debug('wakeup-storage', 'Migrated config to new default models')\n }\n return existing\n }\n const defaultConfig = getDefaultConfig()\n saveWakeupConfig(defaultConfig)\n return defaultConfig\n}\n\n// ============================================================================\n// History Operations\n// ============================================================================\n\n/**\n * Load trigger history\n */\nexport function loadTriggerHistory(): TriggerRecord[] {\n return readJsonFile<TriggerRecord[]>(HISTORY_FILE_NAME, [])\n}\n\n/**\n * Save trigger history\n */\nexport function saveTriggerHistory(history: TriggerRecord[]): void {\n writeJsonFile(HISTORY_FILE_NAME, history)\n}\n\n/**\n * Add a trigger record to history (maintains ring buffer)\n */\nexport function addTriggerRecord(record: TriggerRecord): void {\n const history = loadTriggerHistory()\n \n // Add new record at the beginning\n history.unshift(record)\n \n // Trim to max entries\n if (history.length > MAX_HISTORY_ENTRIES) {\n history.splice(MAX_HISTORY_ENTRIES)\n }\n \n saveTriggerHistory(history)\n debug('wakeup-storage', `Added trigger record (total: ${history.length})`)\n}\n\n/**\n * Get recent trigger history\n */\nexport function getRecentHistory(limit: number = 10): TriggerRecord[] {\n const history = loadTriggerHistory()\n return history.slice(0, limit)\n}\n\n/**\n * Get last trigger record\n */\nexport function getLastTrigger(): TriggerRecord | null {\n const history = loadTriggerHistory()\n return history.length > 0 ? history[0] : null\n}\n\n/**\n * Clear trigger history\n */\nexport function clearTriggerHistory(): void {\n saveTriggerHistory([])\n debug('wakeup-storage', 'Cleared trigger history')\n}\n\n// ============================================================================\n// Reset State Operations\n// ============================================================================\n\n/**\n * Load reset deduplication state\n */\nexport function loadResetState(): ResetState {\n return readJsonFile<ResetState>(RESET_STATE_FILE_NAME, {})\n}\n\n/**\n * Save reset state\n */\nexport function saveResetState(state: ResetState): void {\n writeJsonFile(RESET_STATE_FILE_NAME, state)\n}\n\n/**\n * Update reset state for a specific model\n */\nexport function updateResetState(modelKey: string, resetAt: string): void {\n const state = loadResetState()\n \n state[modelKey] = {\n lastResetAt: resetAt,\n lastTriggeredTime: new Date().toISOString()\n }\n \n saveResetState(state)\n debug('wakeup-storage', `Updated reset state for ${modelKey}`)\n}\n\n/**\n * Get reset state for a specific model\n */\nexport function getModelResetState(modelKey: string): { lastResetAt: string; lastTriggeredTime: string } | null {\n const state = loadResetState()\n return state[modelKey] || null\n}\n\n/**\n * Clear reset state\n */\nexport function clearResetState(): void {\n saveResetState({})\n debug('wakeup-storage', 'Cleared reset state')\n}\n\n// ============================================================================\n// Model Mapping Operations\n// ============================================================================\n\n/**\n * Load model ID to constant mapping\n */\nexport function loadModelMapping(): ModelMapping {\n return readJsonFile<ModelMapping>(MODEL_MAPPING_FILE_NAME, {})\n}\n\n/**\n * Save model mapping\n */\nexport function saveModelMapping(mapping: ModelMapping): void {\n writeJsonFile(MODEL_MAPPING_FILE_NAME, mapping)\n debug('wakeup-storage', `Saved model mapping (${Object.keys(mapping).length} models)`)\n}\n\n/**\n * Update model mapping with new entries\n * Merges with existing mappings\n */\nexport function updateModelMapping(newMappings: ModelMapping): void {\n const existing = loadModelMapping()\n const merged = { ...existing, ...newMappings }\n saveModelMapping(merged)\n}\n\n/**\n * Get model constant for a model ID\n */\nexport function getModelConstant(modelId: string): string | undefined {\n const mapping = loadModelMapping()\n return mapping[modelId]\n}\n\n/**\n * Get reset key for a model (uses constant if available, else ID)\n */\nexport function getResetKey(modelId: string): string {\n return getModelConstant(modelId) || modelId\n}\n","/**\n * Account resolver for auto wake-up\n * Resolves which accounts to use for triggering based on config and availability\n */\n\nimport { debug } from '../core/logger.js'\nimport { getAccountManager } from '../accounts/manager.js'\n\n/**\n * Resolve which accounts to use for triggering\n * @param selectedAccounts Explicitly selected accounts from config (may be undefined)\n * @returns Array of valid account emails to use for triggering\n */\nexport function resolveAccounts(selectedAccounts?: string[]): string[] {\n const accountManager = getAccountManager()\n \n // Case 1: Explicit selection (even if empty array)\n if (selectedAccounts !== undefined) {\n debug('account-resolver', `Explicit account selection: ${selectedAccounts.length} accounts`)\n \n // Filter to only valid accounts\n const validAccounts = selectedAccounts.filter(email => {\n if (!accountManager.hasAccount(email)) {\n debug('account-resolver', `Account ${email} not found, skipping`)\n return false\n }\n \n const status = accountManager.getAccountStatus(email)\n if (status === 'invalid') {\n debug('account-resolver', `Account ${email} is invalid, skipping`)\n return false\n }\n \n // 'valid' or 'expired' (expired can be refreshed)\n return true\n })\n \n debug('account-resolver', `Resolved ${validAccounts.length} valid accounts from selection`)\n return validAccounts\n }\n \n // Case 2: No explicit selection - use fallback logic\n debug('account-resolver', 'No explicit selection, using fallback logic')\n \n // Prefer active account if valid\n const activeEmail = accountManager.getActiveEmail()\n if (activeEmail) {\n const status = accountManager.getAccountStatus(activeEmail)\n if (status === 'valid' || status === 'expired') {\n debug('account-resolver', `Using active account: ${activeEmail}`)\n return [activeEmail]\n }\n debug('account-resolver', `Active account ${activeEmail} is ${status}, trying fallback`)\n }\n \n // Fallback: use first available valid account\n const allEmails = accountManager.getAccountEmails()\n for (const email of allEmails) {\n const status = accountManager.getAccountStatus(email)\n if (status === 'valid' || status === 'expired') {\n debug('account-resolver', `Fallback to first valid account: ${email}`)\n return [email]\n }\n }\n \n // No valid accounts\n debug('account-resolver', 'No valid accounts found')\n return []\n}\n\n/**\n * Check if any accounts are available for triggering\n */\nexport function hasValidAccounts(selectedAccounts?: string[]): boolean {\n return resolveAccounts(selectedAccounts).length > 0\n}\n\n/**\n * Get a friendly description of account resolution state\n */\nexport function getAccountResolutionStatus(selectedAccounts?: string[]): string {\n const resolved = resolveAccounts(selectedAccounts)\n \n if (resolved.length === 0) {\n if (selectedAccounts !== undefined && selectedAccounts.length > 0) {\n return 'Selected accounts are invalid or not found'\n }\n return 'No valid accounts available'\n }\n \n if (resolved.length === 1) {\n return `Using account: ${resolved[0]}`\n }\n \n return `Using ${resolved.length} accounts: ${resolved.join(', ')}`\n}\n","/**\n * Schedule converter for auto wake-up\n * Converts schedule configuration to cron expressions\n */\n\nimport type { WakeupConfig, WeeklySchedule } from './types.js'\n\n/**\n * Convert wakeup config to cron expression\n * @param config Wake-up configuration\n * @returns Cron expression string (5 fields: minute hour day month weekday)\n */\nexport function configToCronExpression(config: WakeupConfig): string {\n // If custom cron expression provided, use it directly\n if (config.cronExpression) {\n return config.cronExpression\n }\n \n switch (config.scheduleMode) {\n case 'interval':\n return intervalToCron(config.intervalHours || 6)\n \n case 'daily':\n return dailyToCron(config.dailyTimes || ['09:00'])\n \n case 'weekly':\n return weeklyToCron(config.weeklySchedule || {})\n \n case 'custom':\n // Should have cronExpression set, fallback to every 6 hours\n return '0 */6 * * *'\n \n default:\n throw new Error(`Unknown schedule mode: ${config.scheduleMode}`)\n }\n}\n\n/**\n * Interval mode: every N hours\n * Example: every 6 hours produces cron \"0 STAR/6 * * *\" (STAR = asterisk)\n */\nfunction intervalToCron(hours: number): string {\n if (hours < 1 || hours > 23) {\n throw new Error('Interval hours must be between 1 and 23')\n }\n return `0 */${hours} * * *`\n}\n\n/**\n * Daily mode: at specific times each day\n * For multiple times, creates comma-separated hours\n * Example: [\"09:00\", \"18:00\"] produces cron \"0 9,18 * * *\"\n */\nfunction dailyToCron(times: string[]): string {\n if (times.length === 0) {\n throw new Error('Daily mode requires at least one time')\n }\n \n // Parse all times\n const parsedTimes = times.map(parseTime)\n \n // Group by minute (most common case: all same minute, usually :00)\n // For simplicity, use the first time's minute and all hours\n const [firstHour, firstMinute] = parsedTimes[0]\n const hours = parsedTimes.map(([h]) => h)\n \n // If all times have the same minute, use comma-separated hours\n const allSameMinute = parsedTimes.every(([, m]) => m === firstMinute)\n \n if (allSameMinute) {\n return `${firstMinute} ${hours.join(',')} * * *`\n }\n \n // Different minutes - just use the first time\n // (Multiple cron entries would require multiple install calls)\n return `${firstMinute} ${firstHour} * * *`\n}\n\n/**\n * Weekly mode: specific days at specific times\n * Example: day 1 at 09:00 and day 5 at 17:00 produces cron \"0 9 * * 1\"\n * Note: For multiple days with same time, uses comma-separated days\n */\nfunction weeklyToCron(schedule: WeeklySchedule): string {\n const days = Object.keys(schedule).map(Number).sort()\n \n if (days.length === 0) {\n throw new Error('Weekly mode requires at least one day')\n }\n \n // Use first day's first time\n const firstDay = days[0]\n const firstDayTimes = schedule[firstDay]\n \n if (!firstDayTimes || firstDayTimes.length === 0) {\n throw new Error(`No times specified for day ${firstDay}`)\n }\n \n const [hour, minute] = parseTime(firstDayTimes[0])\n \n // Create day list\n const daysStr = days.join(',')\n \n return `${minute} ${hour} * * ${daysStr}`\n}\n\n/**\n * Parse time string \"HH:MM\" to [hour, minute]\n */\nfunction parseTime(timeStr: string): [number, number] {\n const match = timeStr.match(/^(\\d{1,2}):(\\d{2})$/)\n if (!match) {\n throw new Error(`Invalid time format: ${timeStr}. Expected HH:MM`)\n }\n \n const hour = parseInt(match[1], 10)\n const minute = parseInt(match[2], 10)\n \n if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {\n throw new Error(`Invalid time values: ${timeStr}`)\n }\n \n return [hour, minute]\n}\n\n/**\n * Validate a cron expression (basic validation)\n * @param expr Cron expression to validate\n * @returns true if valid, false otherwise\n */\nexport function validateCronExpression(expr: string): boolean {\n // Basic validation: 5 fields (minute hour day month weekday)\n const parts = expr.trim().split(/\\s+/)\n if (parts.length !== 5) {\n return false\n }\n \n // Each field should match basic cron syntax\n const fieldPattern = /^(\\*|[\\d,\\-\\/\\*]+)$/\n return parts.every(part => fieldPattern.test(part))\n}\n\n/**\n * Get human-readable description of schedule\n */\nexport function getScheduleDescription(config: WakeupConfig): string {\n if (!config.enabled) {\n return 'Disabled'\n }\n \n if (config.wakeOnReset) {\n const cooldown = config.resetCooldownMinutes || 10\n return `Quota-reset based (${cooldown}min cooldown)`\n }\n \n switch (config.scheduleMode) {\n case 'interval':\n const hours = config.intervalHours || 6\n return `Every ${hours} hour${hours > 1 ? 's' : ''}`\n \n case 'daily':\n const times = config.dailyTimes || ['09:00']\n if (times.length === 1) {\n return `Daily at ${times[0]}`\n }\n return `Daily at ${times.join(', ')}`\n \n case 'weekly':\n const days = Object.keys(config.weeklySchedule || {}).map(Number)\n const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']\n const dayList = days.map(d => dayNames[d]).join(', ')\n return `Weekly on ${dayList}`\n \n case 'custom':\n return `Custom: ${config.cronExpression || 'Not set'}`\n \n default:\n return 'Unknown schedule'\n }\n}\n\n/**\n * Calculate next run time from cron expression (simplified)\n * Returns a human-readable estimate\n */\nexport function getNextRunEstimate(cronExpression: string): string {\n try {\n const parts = cronExpression.trim().split(/\\s+/)\n if (parts.length !== 5) {\n return 'Invalid cron'\n }\n \n const [minute, hour, day, month, weekday] = parts\n \n // Simple cases\n if (hour.startsWith('*/')) {\n const interval = parseInt(hour.substring(2), 10)\n return `Every ${interval} hour${interval > 1 ? 's' : ''}`\n }\n \n if (day === '*' && month === '*' && weekday === '*') {\n // Daily - show specific time\n const displayHour = hour.includes(',') ? hour.split(',')[0] : hour\n return `Daily at ${displayHour.padStart(2, '0')}:${minute.padStart(2, '0')}`\n }\n \n if (weekday !== '*') {\n const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']\n const dayNums = weekday.split(',').map(Number)\n const dayList = dayNums.map(d => dayNames[d] || d).join(', ')\n return `${dayList} at ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`\n }\n \n return cronExpression\n } catch {\n return cronExpression\n }\n}\n","/**\n * Cron installer for auto wake-up\n * Manages cron job installation for macOS/Linux\n */\n\nimport { execSync, exec } from 'child_process'\nimport { promisify } from 'util'\nimport { debug } from '../core/logger.js'\nimport type { CronInstallResult, CronStatus } from './types.js'\n\nconst execAsync = promisify(exec)\n\n// Comment marker to identify our cron entries\nconst CRON_COMMENT_MARKER = 'antigravity-usage-wakeup'\n\n/**\n * Get PATH directories for cron environment\n * Returns directories where node and npm binaries are found\n * This makes cron jobs portable across different machines and Node.js installations\n */\nfunction getBinDirectories(): string[] {\n const dirs = new Set<string>()\n \n try {\n // Get node's bin directory from current process\n const nodePath = process.execPath\n const nodeDir = nodePath.substring(0, nodePath.lastIndexOf('/'))\n if (nodeDir) {\n dirs.add(nodeDir)\n debug('cron-installer', `Found node bin dir: ${nodeDir}`)\n }\n } catch {\n debug('cron-installer', 'Could not determine node bin directory')\n }\n \n try {\n // Get npm global bin directory\n const npmBin = execSync('npm bin -g', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe']\n }).trim()\n if (npmBin) {\n dirs.add(npmBin)\n debug('cron-installer', `Found npm bin dir: ${npmBin}`)\n }\n } catch {\n debug('cron-installer', 'Could not determine npm bin directory')\n }\n \n // Try to get user's current PATH as fallback\n // This helps capture paths from nvm, homebrew, etc.\n if (process.env.PATH) {\n const userPaths = process.env.PATH.split(':').filter(p => {\n // Include paths that might contain node or npm binaries\n return p.includes('node') || p.includes('npm') || \n p.includes('nvm') || p.includes('.local') ||\n p === '/usr/local/bin' || p === '/opt/homebrew/bin'\n })\n userPaths.forEach(p => {\n if (p) {\n dirs.add(p)\n debug('cron-installer', `Added user PATH: ${p}`)\n }\n })\n }\n \n // Add standard system paths (always include these)\n dirs.add('/usr/local/bin')\n dirs.add('/usr/bin')\n dirs.add('/bin')\n dirs.add('/opt/homebrew/bin') // For Apple Silicon Macs\n \n return Array.from(dirs)\n}\n\n/**\n * Load current crontab entries\n */\nasync function loadCrontab(): Promise<string[]> {\n try {\n const { stdout } = await execAsync('crontab -l 2>/dev/null || echo \"\"')\n const lines = stdout.split('\\n').filter(line => line.trim())\n debug('cron-installer', `Loaded ${lines.length} crontab entries`)\n return lines\n } catch {\n debug('cron-installer', 'No existing crontab or error loading')\n return []\n }\n}\n\n/**\n * Save crontab entries\n */\nasync function saveCrontab(lines: string[]): Promise<void> {\n const content = lines.join('\\n') + '\\n'\n \n try {\n // Write to temp file and load into crontab\n const { exec: execCallback } = await import('child_process')\n \n await new Promise<void>((resolve, reject) => {\n const proc = execCallback('crontab -', (err) => {\n if (err) reject(err)\n else resolve()\n })\n proc.stdin?.write(content)\n proc.stdin?.end()\n })\n \n debug('cron-installer', 'Saved crontab successfully')\n } catch (err) {\n debug('cron-installer', 'Error saving crontab:', err)\n throw err\n }\n}\n\n/**\n * Remove all antigravity-usage-wakeup entries from crontab lines\n */\nfunction removeWakeupEntries(lines: string[]): string[] {\n return lines.filter(line => !line.includes(CRON_COMMENT_MARKER))\n}\n\n/**\n * Check if running on a supported platform\n */\nexport function isCronSupported(): boolean {\n return process.platform === 'darwin' || process.platform === 'linux'\n}\n\n/**\n * Install cron job for scheduled wake-up\n * @param cronExpression Cron expression (5 fields: minute hour day month weekday)\n * @returns Installation result with success status or manual instructions\n */\nexport async function installCronJob(cronExpression: string): Promise<CronInstallResult> {\n if (!isCronSupported()) {\n return {\n success: false,\n error: `Cron is not supported on ${process.platform}. Windows Task Scheduler support coming soon.`,\n manualInstructions: getWindowsInstructions(cronExpression)\n }\n }\n \n try {\n // Get PATH directories - auto-detected from current environment\n // This makes the cron job portable across different machines and Node.js installations\n const binDirs = getBinDirectories()\n const pathValue = binDirs.join(':')\n \n // Load existing crontab\n const lines = await loadCrontab()\n \n // Remove any existing antigravity-usage entries (both PATH and job lines)\n const filteredLines = removeWakeupEntries(lines)\n \n // Add PATH if not already set for other cron jobs\n const hasPath = filteredLines.some(line => line.startsWith('PATH='))\n if (!hasPath) {\n filteredLines.unshift(`PATH=${pathValue}`)\n }\n \n // Create new cron entry with simple, portable command\n // Using 'antigravity-usage' instead of absolute paths makes it work anywhere\n const cronLine = `${cronExpression} antigravity-usage wakeup trigger --scheduled # ${CRON_COMMENT_MARKER}`\n \n // Add new entry\n filteredLines.push(cronLine)\n \n // Save crontab\n await saveCrontab(filteredLines)\n \n debug('cron-installer', `Installed cron job: ${cronLine}`)\n debug('cron-installer', `Using PATH: ${pathValue}`)\n \n return {\n success: true,\n cronExpression\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err)\n debug('cron-installer', `Failed to install cron job: ${errorMessage}`)\n \n return {\n success: false,\n error: errorMessage,\n manualInstructions: getManualInstructions(cronExpression)\n }\n }\n}\n\n/**\n * Uninstall cron job\n * @returns true if successful, false otherwise\n */\nexport async function uninstallCronJob(): Promise<boolean> {\n if (!isCronSupported()) {\n debug('cron-installer', 'Cron not supported on this platform')\n return false\n }\n \n try {\n // Load existing crontab\n const lines = await loadCrontab()\n \n // Remove our entries\n const filteredLines = removeWakeupEntries(lines)\n \n // If nothing changed, already uninstalled\n if (filteredLines.length === lines.length) {\n debug('cron-installer', 'No cron job found to uninstall')\n return true\n }\n \n // Save updated crontab\n await saveCrontab(filteredLines)\n \n debug('cron-installer', 'Uninstalled cron job successfully')\n return true\n } catch (err) {\n debug('cron-installer', 'Failed to uninstall cron job:', err)\n return false\n }\n}\n\n/**\n * Check if cron job is installed\n */\nexport async function isCronJobInstalled(): Promise<boolean> {\n if (!isCronSupported()) {\n return false\n }\n \n try {\n const lines = await loadCrontab()\n return lines.some(line => line.includes(CRON_COMMENT_MARKER))\n } catch {\n return false\n }\n}\n\n/**\n * Get current cron job status\n */\nexport async function getCronStatus(): Promise<CronStatus> {\n if (!isCronSupported()) {\n return { installed: false }\n }\n \n try {\n const lines = await loadCrontab()\n const cronLine = lines.find(line => line.includes(CRON_COMMENT_MARKER))\n \n if (!cronLine) {\n return { installed: false }\n }\n \n // Extract cron expression from line\n const parts = cronLine.trim().split(/\\s+/)\n const cronExpression = parts.slice(0, 5).join(' ')\n \n return {\n installed: true,\n cronExpression,\n nextRun: getNextRunDescription(cronExpression)\n }\n } catch {\n return { installed: false }\n }\n}\n\n/**\n * Generate manual instructions for cron setup\n */\nfunction getManualInstructions(cronExpression: string): string {\n const binDirs = getBinDirectories()\n const pathValue = binDirs.join(':')\n \n return `\nFailed to automatically install cron job. Please add manually:\n\n1. Open terminal and run: crontab -e\n\n2. Add these lines:\n PATH=${pathValue}\n ${cronExpression} antigravity-usage wakeup trigger --scheduled # ${CRON_COMMENT_MARKER}\n\n3. Save and exit the editor\n\nTo verify, run: crontab -l\n`.trim()\n}\n\n/**\n * Generate instructions for Windows users\n */\nfunction getWindowsInstructions(cronExpression: string): string {\n return `\nWindows Task Scheduler support is not yet available.\n\nTo set up manually using Task Scheduler:\n\n1. Open Task Scheduler (taskschd.msc)\n2. Create a new Basic Task\n3. Set trigger: Based on your schedule (${cronExpression})\n4. Set action: Start a program\n - Program: antigravity-usage\n - Arguments: wakeup trigger --scheduled\n5. Save the task\n\nAlternatively, use Windows Subsystem for Linux (WSL) with cron.\n`.trim()\n}\n\n/**\n * Get human-readable description of next run\n */\nfunction getNextRunDescription(cronExpression: string): string {\n try {\n const parts = cronExpression.split(/\\s+/)\n if (parts.length !== 5) return 'Unknown'\n \n const [minute, hour] = parts\n \n // Interval-based\n if (hour.startsWith('*/')) {\n const hours = parseInt(hour.substring(2), 10)\n const now = new Date()\n const currentHour = now.getHours()\n const nextHour = Math.ceil((currentHour + 1) / hours) * hours\n const isToday = nextHour < 24\n return isToday ? `Today around ${nextHour}:00` : 'Tomorrow'\n }\n \n // Specific time\n const hourNum = parseInt(hour.split(',')[0], 10)\n const minuteNum = parseInt(minute, 10)\n const now = new Date()\n const currentMinutes = now.getHours() * 60 + now.getMinutes()\n const targetMinutes = hourNum * 60 + minuteNum\n \n if (targetMinutes > currentMinutes) {\n return `Today at ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`\n }\n return `Tomorrow at ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`\n } catch {\n return 'Unknown'\n }\n}\n","/**\n * Trigger service for auto wake-up\n * Executes actual AI requests to warm up models\n */\n\nimport { debug } from '../core/logger.js'\nimport { getTokenManagerForAccount } from '../google/token-manager.js'\nimport { CloudCodeClient } from '../google/cloudcode.js'\nimport { addTriggerRecord } from './storage.js'\nimport type { \n TriggerOptions, \n TriggerResult, \n ModelTriggerResult,\n TriggerRecord,\n TokenUsage\n} from './types.js'\n\n// Constants\nconst DEFAULT_PROMPT = 'hi'\nconst REQUEST_TIMEOUT_MS = 30000 // 30 seconds\nconst MAX_CONCURRENT_REQUESTS = 4\n\n/**\n * Execute trigger for specified models and account\n * @param options Trigger options including models, account, and prompt\n * @returns Trigger result with success status and per-model results\n */\nexport async function executeTrigger(options: TriggerOptions): Promise<TriggerResult> {\n const { \n models, \n accountEmail, \n triggerType, \n triggerSource, \n customPrompt,\n maxOutputTokens \n } = options\n \n debug('trigger-service', `Executing trigger for ${models.length} models with account ${accountEmail}`)\n \n if (models.length === 0) {\n debug('trigger-service', 'No models to trigger')\n return { success: true, results: [] }\n }\n \n // Get or create token manager for this account\n let tokenManager\n try {\n tokenManager = getTokenManagerForAccount(accountEmail)\n } catch (err) {\n debug('trigger-service', `Failed to get token manager for ${accountEmail}:`, err)\n \n // Record failure for all models\n const results: ModelTriggerResult[] = models.map(modelId => ({\n modelId,\n success: false,\n durationMs: 0,\n error: `Failed to get credentials for ${accountEmail}`\n }))\n \n recordResults(results, options)\n return { success: false, results }\n }\n \n // Ensure we have valid tokens (trigger refresh if needed)\n try {\n await tokenManager.getValidAccessToken()\n } catch (err) {\n // Extract detailed error message for better diagnostics\n let errorMessage = `Authentication failed for ${accountEmail}`\n \n if (err && typeof err === 'object' && 'getDetailedMessage' in err) {\n // TokenRefreshError with detailed message\n errorMessage = (err as { getDetailedMessage: () => string }).getDetailedMessage()\n } else if (err instanceof Error) {\n errorMessage = `Token refresh failed: ${err.message}`\n }\n \n debug('trigger-service', `Failed to refresh token for ${accountEmail}:`, err)\n \n const results: ModelTriggerResult[] = models.map(modelId => ({\n modelId,\n success: false,\n durationMs: 0,\n error: errorMessage\n }))\n \n recordResults(results, options)\n return { success: false, results }\n }\n \n // Create CloudCode client\n const client = new CloudCodeClient(tokenManager)\n \n // Debug: check if projectId was loaded from cache\n debug('trigger-service', `Account ${accountEmail} projectId from tokenManager: ${tokenManager.getProjectId()}`)\n \n // Resolve project ID (may require onboarding if first time)\n try {\n const projectId = await client.resolveProjectId()\n if (projectId) {\n debug('trigger-service', `Project ID resolved: ${projectId}`)\n // Save for future use\n tokenManager.setProjectId(projectId)\n } else {\n debug('trigger-service', 'WARNING: Could not resolve project ID')\n }\n } catch (err) {\n debug('trigger-service', 'Failed to resolve project ID:', err)\n }\n \n // Prepare prompt\n const userPrompt = customPrompt || DEFAULT_PROMPT\n \n // Trigger models with concurrency limit\n const results: ModelTriggerResult[] = []\n \n // Process in batches of MAX_CONCURRENT_REQUESTS\n for (let i = 0; i < models.length; i += MAX_CONCURRENT_REQUESTS) {\n const batch = models.slice(i, i + MAX_CONCURRENT_REQUESTS)\n \n debug('trigger-service', `Processing batch ${i / MAX_CONCURRENT_REQUESTS + 1}: ${batch.join(', ')}`)\n \n const batchResults = await Promise.all(\n batch.map(modelId => triggerSingleModel(client, modelId, userPrompt, maxOutputTokens))\n )\n \n results.push(...batchResults)\n }\n \n // Record results in history\n recordResults(results, options)\n \n const allSuccess = results.every(r => r.success)\n const successCount = results.filter(r => r.success).length\n \n debug('trigger-service', `Trigger complete: ${successCount}/${results.length} succeeded`)\n \n return { success: allSuccess, results }\n}\n\n/**\n * Trigger a single model\n */\nasync function triggerSingleModel(\n client: CloudCodeClient,\n modelId: string,\n prompt: string,\n maxTokens?: number\n): Promise<ModelTriggerResult> {\n const startTime = Date.now()\n \n debug('trigger-service', `Triggering model: ${modelId}`)\n \n try {\n // Create timeout promise\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error('Request timed out')), REQUEST_TIMEOUT_MS)\n })\n \n // Race between actual request and timeout\n const response = await Promise.race([\n client.generateContent(modelId, prompt, maxTokens),\n timeoutPromise\n ])\n \n const durationMs = Date.now() - startTime\n \n debug('trigger-service', `Model ${modelId} responded in ${durationMs}ms`)\n \n return {\n modelId,\n success: true,\n durationMs,\n response: response.text.substring(0, 500), // Truncate to 500 chars\n tokensUsed: response.tokensUsed\n }\n } catch (err) {\n const durationMs = Date.now() - startTime\n const errorMessage = err instanceof Error ? err.message : String(err)\n \n debug('trigger-service', `Model ${modelId} failed after ${durationMs}ms: ${errorMessage}`)\n \n return {\n modelId,\n success: false,\n durationMs,\n error: errorMessage\n }\n }\n}\n\n/**\n * Record trigger results in history\n */\nfunction recordResults(results: ModelTriggerResult[], options: TriggerOptions): void {\n const { triggerType, triggerSource, accountEmail, customPrompt } = options\n const prompt = customPrompt || DEFAULT_PROMPT\n \n // Create a record for each model result\n for (const result of results) {\n const record: TriggerRecord = {\n timestamp: new Date().toISOString(),\n success: result.success,\n triggerType,\n triggerSource,\n models: [result.modelId],\n accountEmail,\n durationMs: result.durationMs,\n prompt,\n response: result.response,\n error: result.error,\n tokensUsed: result.tokensUsed\n }\n \n addTriggerRecord(record)\n }\n}\n\n/**\n * Execute a quick test trigger (for manual testing)\n * @param modelId Model to test\n * @param accountEmail Account to use\n * @param prompt Optional custom prompt\n */\nexport async function testTrigger(\n modelId: string,\n accountEmail: string,\n prompt?: string\n): Promise<ModelTriggerResult> {\n const result = await executeTrigger({\n models: [modelId],\n accountEmail,\n triggerType: 'manual',\n triggerSource: 'manual',\n customPrompt: prompt\n })\n \n return result.results[0] || {\n modelId,\n success: false,\n durationMs: 0,\n error: 'No result returned'\n }\n}\n","/**\n * Reset detector for auto wake-up\n * \n * Smart trigger logic:\n * - Triggers ALL available models from quota snapshot\n * - Triggers for ALL valid accounts\n * - Only triggers when model is \"unused\": 100% remaining AND ~5h until reset\n */\n\nimport { debug } from '../core/logger.js'\nimport type { QuotaSnapshot, ModelQuotaInfo } from '../quota/types.js'\nimport { \n loadWakeupConfig, \n loadResetState, \n updateResetState\n} from './storage.js'\nimport { getAccountManager } from '../accounts/manager.js'\nimport { executeTrigger } from './trigger-service.js'\nimport type { DetectionResult } from './types.js'\n\n// Smart trigger thresholds\nconst FULL_QUOTA_THRESHOLD = 99 // Consider \"full\" if >= 99%\nconst RESET_TIME_MIN_HOURS = 4.5 // At least 4.5 hours until reset\nconst RESET_TIME_MAX_HOURS = 5.5 // At most 5.5 hours until reset (catches the ~5h window)\nconst RESET_TIME_MIN_MS = RESET_TIME_MIN_HOURS * 60 * 60 * 1000\nconst RESET_TIME_MAX_MS = RESET_TIME_MAX_HOURS * 60 * 60 * 1000\n\n// Cooldown between triggers for same model\nconst DEFAULT_COOLDOWN_MS = 60 * 60 * 1000 // 1 hour (since we're looking at ~5h window)\n\n/**\n * Check if a model is \"unused\" and should be triggered\n * \n * Unused = 100% quota remaining AND reset time is approximately 5 hours\n * (meaning the model hasn't been used this quota cycle)\n */\nexport function isModelUnused(model: ModelQuotaInfo): boolean {\n // Must have remaining percentage data\n if (model.remainingPercentage === undefined) {\n debug('reset-detector', `${model.modelId}: No remaining percentage data`)\n return false\n }\n \n // Check if quota is full (100% or very close)\n if (model.remainingPercentage < FULL_QUOTA_THRESHOLD) {\n debug('reset-detector', `${model.modelId}: Not full (${model.remainingPercentage}%)`)\n return false\n }\n \n // Must have time until reset data\n if (model.timeUntilResetMs === undefined) {\n debug('reset-detector', `${model.modelId}: No reset time data`)\n return false\n }\n \n // Check if reset time is in the ~5h window (4.5h to 5.5h)\n // This means it just reset and hasn't been used\n if (model.timeUntilResetMs < RESET_TIME_MIN_MS || model.timeUntilResetMs > RESET_TIME_MAX_MS) {\n const hoursUntilReset = (model.timeUntilResetMs / (60 * 60 * 1000)).toFixed(1)\n debug('reset-detector', `${model.modelId}: Reset time ${hoursUntilReset}h not in 4.5-5.5h window`)\n return false\n }\n \n debug('reset-detector', `${model.modelId}: UNUSED - 100% remaining, ~5h until reset`)\n return true\n}\n\n/**\n * Get all valid account emails\n */\nfunction getAllValidAccounts(): string[] {\n const accountManager = getAccountManager()\n const allEmails = accountManager.getAccountEmails()\n \n return allEmails.filter(email => {\n const status = accountManager.getAccountStatus(email)\n return status === 'valid' || status === 'expired' // Expired can be refreshed\n })\n}\n\n/**\n * Detect unused models and trigger wake-up for all accounts\n * \n * New smart logic:\n * 1. Check ALL models in the quota snapshot\n * 2. Find models that are \"unused\" (100% + ~5h reset)\n * 3. Trigger for ALL valid accounts\n */\nexport async function detectResetAndTrigger(snapshot: QuotaSnapshot): Promise<DetectionResult> {\n debug('reset-detector', 'Checking for unused models (smart trigger)')\n \n // Load config\n const config = loadWakeupConfig()\n \n // Must be enabled\n if (!config || !config.enabled) {\n debug('reset-detector', 'Wakeup is not enabled')\n return { triggered: false, triggeredModels: [] }\n }\n \n // Get ALL valid accounts\n const accounts = getAllValidAccounts()\n if (accounts.length === 0) {\n debug('reset-detector', 'No valid accounts available')\n return { triggered: false, triggeredModels: [] }\n }\n \n debug('reset-detector', `Found ${accounts.length} valid accounts`)\n \n // Load reset state for cooldown\n const resetState = loadResetState()\n const now = Date.now()\n \n // Find ALL unused models (check every model in snapshot)\n const modelsToTrigger: string[] = []\n \n for (const model of snapshot.models) {\n // Check if model is unused\n if (!isModelUnused(model)) {\n continue\n }\n \n // Check cooldown (don't trigger same model too frequently)\n const previousState = resetState[model.modelId]\n if (previousState) {\n const lastTriggered = new Date(previousState.lastTriggeredTime).getTime()\n const cooldownRemaining = DEFAULT_COOLDOWN_MS - (now - lastTriggered)\n if (cooldownRemaining > 0) {\n debug('reset-detector', `${model.modelId}: In cooldown (${Math.round(cooldownRemaining / 60000)}min remaining)`)\n continue\n }\n }\n \n modelsToTrigger.push(model.modelId)\n \n // Update state to prevent re-triggering\n updateResetState(model.modelId, model.resetTime || new Date().toISOString())\n }\n \n if (modelsToTrigger.length === 0) {\n debug('reset-detector', 'No unused models to trigger')\n return { triggered: false, triggeredModels: [] }\n }\n \n console.log(`\\n🔄 Found ${modelsToTrigger.length} unused model(s): ${modelsToTrigger.join(', ')}`)\n console.log(` Triggering for ${accounts.length} account(s)...`)\n \n // Trigger for ALL accounts\n let successCount = 0\n for (const accountEmail of accounts) {\n try {\n const result = await executeTrigger({\n models: modelsToTrigger,\n accountEmail,\n triggerType: 'auto',\n triggerSource: 'quota_reset',\n customPrompt: config.customPrompt,\n maxOutputTokens: config.maxOutputTokens\n })\n \n const modelSuccess = result.results.filter(r => r.success).length\n console.log(` ✅ ${accountEmail}: ${modelSuccess}/${modelsToTrigger.length} succeeded`)\n if (modelSuccess > 0) successCount++\n } catch (err) {\n console.log(` ❌ ${accountEmail}: ${err instanceof Error ? err.message : err}`)\n debug('reset-detector', `Trigger failed for ${accountEmail}:`, err)\n }\n }\n \n console.log(`\\n📊 Wake-up complete: ${successCount}/${accounts.length} accounts triggered\\n`)\n \n return { \n triggered: true, \n triggeredModels: modelsToTrigger \n }\n}\n\n/**\n * Get list of unused models for display/testing\n */\nexport function findUnusedModels(snapshot: QuotaSnapshot): ModelQuotaInfo[] {\n return snapshot.models.filter(isModelUnused)\n}\n\n/**\n * Check if any models need triggering (for status display)\n */\nexport function hasUnusedModels(snapshot: QuotaSnapshot): boolean {\n return snapshot.models.some(isModelUnused)\n}\n"],"mappings":"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","names":["URL","readFileSync","join","join","join","readFileSync","existsSync","readFileSync","writeFileSync","mkdirSync","dirname","existsSync","readFileSync","dirname","mkdirSync","writeFileSync","error","URL","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","dirname","existsSync","mkdirSync","writeFileSync","readFileSync","existsSync","EXPIRY_BUFFER_MS","removed","sleep","platform","exec","promisify","execAsync","promisify","exec","platform","https","http","https","http","parsePromptCredits","Table","Table","info","inquirer","Table","join","readFileSync","writeFileSync","existsSync","mkdirSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","exec","promisify","execAsync","promisify","exec","now","results","inquirer","success","Table"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/version.ts","../src/core/logger.ts","../src/google/oauth.ts","../src/accounts/types.ts","../src/accounts/storage.ts","../src/core/env.ts","../src/accounts/config.ts","../src/accounts/cache.ts","../src/accounts/manager.ts","../src/google/storage.ts","../src/core/errors.ts","../src/google/token-manager.ts","../src/commands/login.ts","../src/commands/logout.ts","../src/core/mask.ts","../src/commands/status.ts","../src/google/cloudcode.ts","../src/google/parser.ts","../src/local/process-detector.ts","../src/local/port-detective.ts","../src/local/port-prober.ts","../src/local/connect-client.ts","../src/local/local-parser.ts","../src/quota/service.ts","../src/quota/format.ts","../src/render/table.ts","../src/commands/quota.ts","../src/commands/doctor.ts","../src/commands/accounts.ts","../src/commands/wakeup.ts","../src/wakeup/types.ts","../src/wakeup/storage.ts","../src/wakeup/account-resolver.ts","../src/wakeup/schedule-converter.ts","../src/wakeup/cron-installer.ts","../src/wakeup/trigger-service.ts","../src/wakeup/reset-detector.ts"],"sourcesContent":["/**\n * antigravity-usage CLI entry point\n */\n\nimport { Command } from 'commander'\nimport { version } from './version'\nimport { setDebugMode } from './core/logger.js'\n\n// Import commands\nimport { loginCommand } from './commands/login.js'\nimport { logoutCommand } from './commands/logout.js'\nimport { statusCommand } from './commands/status.js'\nimport { quotaCommand } from './commands/quota.js'\nimport { doctorCommand } from './commands/doctor.js'\nimport { accountsCommand } from './commands/accounts.js'\n\nconst program = new Command()\n\nprogram\n .name('antigravity-usage')\n .description('CLI tool to check Antigravity model quota via Google Cloud Code API')\n .version(version)\n .option('--debug', 'Enable debug mode')\n .hook('preAction', (thisCommand) => {\n const opts = thisCommand.opts()\n if (opts.debug) {\n setDebugMode(true)\n }\n })\n\n// Login command\nprogram\n .command('login')\n .description('Authenticate with Google (adds a new account)')\n .option('--no-browser', 'Do not open browser, print URL instead')\n .option('--manual', 'Manual login flow (copy-paste URL)')\n .option('-p, --port <port>', 'Port for OAuth callback server', parseInt)\n .action(loginCommand)\n\n// Logout command\nprogram\n .command('logout [email]')\n .description('Remove stored credentials')\n .option('--all', 'Logout from all accounts')\n .action((email, options) => logoutCommand(options, email))\n\n// Status command\nprogram\n .command('status')\n .description('Show current authentication status')\n .option('--all', 'Show status for all accounts')\n .option('-a, --account <email>', 'Show status for specific account')\n .action(statusCommand)\n\n// Quota command (default)\nprogram\n .command('quota', { isDefault: true })\n .description('Fetch and display quota information')\n .option('--json', 'Output as JSON')\n .option('-m, --method <method>', 'Method to use: auto (default), local, or google', 'auto')\n .option('--all', 'Show quota for all accounts')\n .option('-a, --account <email>', 'Show quota for specific account')\n .option('--refresh', 'Force refresh (ignore cache)')\n .option('--all-models', 'Include autocomplete models (Gemini 2.5) in quota display')\n .action(quotaCommand)\n\n// Accounts command with subcommands\nconst accountsCmd = program\n .command('accounts')\n .description('Manage multiple accounts')\n\naccountsCmd\n .command('list')\n .description('List all accounts')\n .option('--refresh', 'Show refresh tip')\n .action((options) => accountsCommand('list', [], options))\n\naccountsCmd\n .command('add')\n .description('Add a new account (triggers OAuth login)')\n .action(() => accountsCommand('add', [], {}))\n\naccountsCmd\n .command('switch <email>')\n .description('Switch to a different account')\n .action((email) => accountsCommand('switch', [email], {}))\n\naccountsCmd\n .command('remove <email>')\n .description('Remove an account')\n .option('--force', 'Skip confirmation')\n .action((email, options) => accountsCommand('remove', [email], options))\n\naccountsCmd\n .command('current')\n .description('Show current active account')\n .action(() => accountsCommand('current', [], {}))\n\naccountsCmd\n .command('refresh [email]')\n .description('Refresh account tokens')\n .option('--all', 'Refresh all accounts')\n .action((email, options) => accountsCommand('refresh', email ? [email] : [], options))\n\n// Default action for accounts command (show list)\naccountsCmd.action(() => accountsCommand('list', [], {}))\n\n// Doctor command\nprogram\n .command('doctor')\n .description('Run diagnostics and show configuration')\n .action(doctorCommand)\n\n// Wakeup command with subcommands\nimport { wakeupCommand } from './commands/wakeup.js'\n\nconst wakeupCmd = program\n .command('wakeup')\n .description('Auto wake-up and warm up AI models')\n\nwakeupCmd\n .command('config')\n .description('Configure auto wake-up schedule')\n .action(() => wakeupCommand('config', [], {}))\n\nwakeupCmd\n .command('trigger')\n .description('Execute one trigger cycle (called by cron)')\n .option('--scheduled', 'Mark as scheduled trigger')\n .action((options) => wakeupCommand('trigger', [], options))\n\nwakeupCmd\n .command('install')\n .description('Install wake-up schedule to system cron')\n .action(() => wakeupCommand('install', [], {}))\n\nwakeupCmd\n .command('uninstall')\n .description('Remove wake-up schedule from system cron')\n .action(() => wakeupCommand('uninstall', [], {}))\n\nwakeupCmd\n .command('test')\n .description('Test trigger manually')\n .option('-e, --email <email>', 'Account email to use for testing')\n .option('-m, --model <model>', 'Model ID to test')\n .option('-p, --prompt <prompt>', 'Test prompt to send', 'hi')\n .action((options) => wakeupCommand('test', [], options))\n\nwakeupCmd\n .command('history')\n .description('View trigger history')\n .option('--limit <n>', 'Number of records to show', '10')\n .option('--json', 'Output as JSON')\n .action((options) => wakeupCommand('history', [], options))\n\nwakeupCmd\n .command('status')\n .description('Show wake-up status and configuration')\n .action(() => wakeupCommand('status', [], {}))\n\n// Default action for wakeup command (show status)\nwakeupCmd.action(() => wakeupCommand('status', [], {}))\n\n// Parse and run\nprogram.parse()\n\n","/**\n * Version info - imported from package.json\n */\nimport { readFileSync } from 'fs'\nimport { join, dirname } from 'path'\nimport { fileURLToPath } from 'url'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\n\nconst packageJsonPath = join(__dirname, '../package.json')\nconst packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'))\n\nexport const version = packageJson.version as string\n","/**\n * Logger utility with debug mode support\n */\n\nlet debugMode = false\n\nexport function setDebugMode(enabled: boolean): void {\n debugMode = enabled\n}\n\nexport function isDebugMode(): boolean {\n return debugMode\n}\n\nexport function debug(category: string, message: string, data?: unknown): void {\n if (!debugMode) return\n \n const timestamp = new Date().toISOString()\n const prefix = `[${timestamp}] [${category}]`\n \n if (data !== undefined) {\n console.error(`${prefix} ${message}`, data)\n } else {\n console.error(`${prefix} ${message}`)\n }\n}\n\nexport function info(message: string): void {\n console.log(message)\n}\n\nexport function warn(message: string): void {\n console.warn(`⚠️ ${message}`)\n}\n\nexport function error(message: string): void {\n console.error(`❌ ${message}`)\n}\n\nexport function success(message: string): void {\n console.log(`✅ ${message}`)\n}\n","/**\n * OAuth configuration and flow\n */\n\nimport { createServer, type IncomingMessage, type ServerResponse } from 'node:http'\nimport { URL, URLSearchParams } from 'node:url'\nimport open from 'open'\nimport inquirer from 'inquirer'\nimport { debug, info, error as logError } from '../core/logger.js'\nimport { getAccountManager } from '../accounts/index.js'\nimport type { OAuthTokenResponse, StoredTokens } from '../quota/types.js'\n\n// OAuth configuration\n// Default credentials provided - users can override with environment variables if needed\nconst OAUTH_CONFIG = {\n clientId: process.env.ANTIGRAVITY_OAUTH_CLIENT_ID || '1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com',\n clientSecret: process.env.ANTIGRAVITY_OAUTH_CLIENT_SECRET || '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',\n authUrl: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenUrl: 'https://oauth2.googleapis.com/token',\n scopes: [\n 'https://www.googleapis.com/auth/cloud-platform',\n 'https://www.googleapis.com/auth/userinfo.email'\n ]\n}\n\n// Cloud Code API configuration\nconst CLOUDCODE_CONFIG = {\n baseUrl: 'https://cloudcode-pa.googleapis.com',\n userAgent: 'antigravity',\n metadata: {\n ideType: 'ANTIGRAVITY',\n platform: 'PLATFORM_UNSPECIFIED',\n pluginType: 'GEMINI'\n },\n onboardAttempts: 5,\n onboardDelayMs: 2000\n}\n\ninterface OAuthOptions {\n noBrowser?: boolean\n port?: number\n manual?: boolean\n}\n\ninterface OAuthResult {\n success: boolean\n email?: string\n error?: string\n}\n\n/**\n * Response types for Cloud Code API\n */\ninterface LoadCodeAssistResponse {\n cloudaicompanionProject?: string | { id?: string }\n paidTier?: { id?: string }\n currentTier?: { id?: string }\n allowedTiers?: Array<{ id?: string; isDefault?: boolean }>\n}\n\ninterface OnboardUserResponse {\n done?: boolean\n response?: {\n cloudaicompanionProject?: string | { id?: string }\n }\n}\n\ninterface ProjectIdResult {\n projectId?: string\n tierId?: string\n}\n\n/**\n * Generate a random state parameter for CSRF protection\n */\nfunction generateState(): string {\n return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)\n}\n\n/**\n * Get available port for callback server\n */\nasync function getAvailablePort(preferredPort?: number): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = createServer()\n server.listen(preferredPort || 0, '127.0.0.1', () => {\n const address = server.address()\n if (address && typeof address === 'object') {\n const port = address.port\n server.close(() => resolve(port))\n } else {\n reject(new Error('Failed to get server address'))\n }\n })\n server.on('error', reject)\n })\n}\n\n/**\n * Exchange authorization code for tokens\n */\nasync function exchangeCodeForTokens(code: string, redirectUri: string): Promise<OAuthTokenResponse> {\n debug('oauth', 'Exchanging code for tokens')\n \n const params = new URLSearchParams({\n code,\n client_id: OAUTH_CONFIG.clientId,\n client_secret: OAUTH_CONFIG.clientSecret,\n redirect_uri: redirectUri,\n grant_type: 'authorization_code'\n })\n \n const response = await fetch(OAUTH_CONFIG.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded'\n },\n body: params.toString()\n })\n \n if (!response.ok) {\n const error = await response.text()\n debug('oauth', 'Token exchange failed', error)\n throw new Error(`Token exchange failed: ${response.status} ${error}`)\n }\n \n const data = await response.json() as OAuthTokenResponse\n debug('oauth', 'Token exchange successful')\n return data\n}\n\n/**\n * Get user email from access token\n */\nasync function getUserEmail(accessToken: string): Promise<string | undefined> {\n debug('oauth', 'Fetching user info')\n \n try {\n const response = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {\n headers: {\n Authorization: `Bearer ${accessToken}`\n }\n })\n \n if (response.ok) {\n const data = await response.json() as { email?: string }\n return data.email\n }\n } catch (err) {\n debug('oauth', 'Failed to get user info', err)\n }\n \n return undefined\n}\n\n/**\n * Extract project ID from cloudaicompanionProject field\n * Handles both string and object { id: string } formats\n */\nexport function extractProjectId(value: unknown): string | undefined {\n // Case 1: Non-empty string\n if (typeof value === 'string' && value.length > 0) {\n return value\n }\n \n // Case 2: Object with 'id' property that is a non-empty string\n if (value && typeof value === 'object' && 'id' in value) {\n const id = (value as { id?: unknown }).id\n if (typeof id === 'string' && id.length > 0) {\n return id\n }\n }\n \n // Case 3: Missing or invalid\n return undefined\n}\n\n/**\n * Pick the tier ID to use for onboarding\n * Priority: default tier from allowedTiers > first tier from allowedTiers > 'LEGACY' > tierIdFromLoad\n */\nexport function pickOnboardTier(\n allowedTiers: Array<{ id?: string; isDefault?: boolean }> | undefined,\n tierIdFromLoad?: string\n): string | undefined {\n if (!allowedTiers || allowedTiers.length === 0) {\n return tierIdFromLoad\n }\n \n // Find default tier\n const defaultTier = allowedTiers.find(t => t.isDefault === true && t.id && t.id.length > 0)\n if (defaultTier?.id) {\n return defaultTier.id\n }\n \n // Find first tier with valid ID\n const firstTier = allowedTiers.find(t => t.id && t.id.length > 0)\n if (firstTier?.id) {\n return firstTier.id\n }\n \n // If tiers exist but have no IDs, use LEGACY\n if (allowedTiers.length > 0) {\n return 'LEGACY'\n }\n \n return tierIdFromLoad\n}\n\n/**\n * Sleep helper for retry delays\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\n/**\n * Try to onboard user with retry logic\n * Calls onboardUser endpoint until done=true or max attempts reached\n */\nasync function tryOnboardUser(accessToken: string, tierId: string): Promise<string | undefined> {\n debug('oauth', `Starting onboard flow with tierId: ${tierId}`)\n \n const payload = {\n tierId,\n metadata: CLOUDCODE_CONFIG.metadata\n }\n \n for (let attempt = 1; attempt <= CLOUDCODE_CONFIG.onboardAttempts; attempt++) {\n debug('oauth', `Onboard attempt ${attempt}/${CLOUDCODE_CONFIG.onboardAttempts}`)\n \n try {\n const response = await fetch(`${CLOUDCODE_CONFIG.baseUrl}/v1internal:onboardUser`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n 'User-Agent': CLOUDCODE_CONFIG.userAgent\n },\n body: JSON.stringify(payload)\n })\n \n if (!response.ok) {\n debug('oauth', `Onboard request failed: ${response.status}`)\n // Don't retry on 403/401 - these are permanent failures\n if (response.status === 401 || response.status === 403) {\n debug('oauth', 'Onboarding forbidden or unauthorized, stopping retries')\n return undefined\n }\n } else {\n const data = await response.json() as OnboardUserResponse\n debug('oauth', `Onboard response: done=${data.done}`)\n \n if (data.done === true) {\n const projectId = extractProjectId(data.response?.cloudaicompanionProject)\n if (projectId) {\n debug('oauth', `Onboarding complete, projectId: ${projectId}`)\n return projectId\n }\n debug('oauth', 'Onboarding done but no projectId in response')\n return undefined\n }\n }\n } catch (err) {\n debug('oauth', `Onboard attempt ${attempt} error:`, err)\n }\n \n // Wait before next attempt (unless this is the last attempt)\n if (attempt < CLOUDCODE_CONFIG.onboardAttempts) {\n debug('oauth', `Waiting ${CLOUDCODE_CONFIG.onboardDelayMs}ms before next attempt`)\n await sleep(CLOUDCODE_CONFIG.onboardDelayMs)\n }\n }\n \n debug('oauth', 'Onboarding attempts exhausted')\n return undefined\n}\n\n/**\n * Resolve project ID from Cloud Code API\n * First tries loadCodeAssist, if no projectId then initiates onboarding\n */\nexport async function resolveProjectId(accessToken: string): Promise<ProjectIdResult> {\n debug('oauth', 'Resolving project ID from Cloud Code API')\n \n try {\n // Step 1: Call loadCodeAssist\n const response = await fetch(`${CLOUDCODE_CONFIG.baseUrl}/v1internal:loadCodeAssist`, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n 'User-Agent': CLOUDCODE_CONFIG.userAgent\n },\n body: JSON.stringify({ metadata: CLOUDCODE_CONFIG.metadata })\n })\n \n if (!response.ok) {\n debug('oauth', `loadCodeAssist failed: ${response.status}`)\n return { projectId: undefined, tierId: undefined }\n }\n \n const data = await response.json() as LoadCodeAssistResponse\n \n // Step 2: Extract project ID and tier\n const projectId = extractProjectId(data.cloudaicompanionProject)\n const tierId = data.paidTier?.id || data.currentTier?.id\n \n // Step 3: If we have projectId, return immediately\n if (projectId) {\n debug('oauth', `Got projectId from loadCodeAssist: ${projectId}`)\n return { projectId, tierId }\n }\n \n // Step 4: No projectId - need to onboard\n debug('oauth', 'No projectId in loadCodeAssist response, initiating onboarding')\n \n const onboardTier = pickOnboardTier(data.allowedTiers, tierId)\n \n if (!onboardTier) {\n debug('oauth', 'Cannot determine tier for onboarding')\n return { projectId: undefined, tierId }\n }\n \n // Step 5: Try onboarding\n const onboardedProjectId = await tryOnboardUser(accessToken, onboardTier)\n \n return {\n projectId: onboardedProjectId,\n tierId: onboardTier\n }\n } catch (err) {\n debug('oauth', 'Error resolving project ID', err)\n return { projectId: undefined, tierId: undefined }\n }\n}\n\n/**\n * Complete login process: exchange code for tokens, get user info, resolve project ID\n */\nasync function completeLogin(code: string, redirectUri: string): Promise<OAuthResult> {\n // Exchange code for tokens\n const tokenResponse = await exchangeCodeForTokens(code, redirectUri)\n \n // Get user email\n const email = await getUserEmail(tokenResponse.access_token)\n \n // Resolve project ID from Cloud Code API (may trigger onboarding if needed)\n let projectId: string | undefined\n try {\n const projectResult = await resolveProjectId(tokenResponse.access_token)\n projectId = projectResult.projectId\n if (projectId) {\n debug('oauth', `Project ID resolved: ${projectId}`)\n } else {\n debug('oauth', 'No project ID obtained (will fetch on demand)')\n }\n } catch (err) {\n debug('oauth', 'Failed to resolve project ID during login (will fetch on demand)', err)\n // Continue without project ID - it will be fetched on demand\n }\n \n // Save tokens using account manager\n const tokens: StoredTokens = {\n accessToken: tokenResponse.access_token,\n refreshToken: tokenResponse.refresh_token || '',\n expiresAt: Date.now() + tokenResponse.expires_in * 1000,\n email,\n projectId\n }\n \n // Add/update account via account manager\n if (email) {\n getAccountManager().addAccount(tokens, email)\n }\n \n return { success: true, email }\n}\n\n/**\n * Start OAuth login flow\n */\nexport async function startOAuthFlow(options: OAuthOptions = {}): Promise<OAuthResult> {\n const port = await getAvailablePort(options.port)\n const redirectUri = `http://127.0.0.1:${port}/callback`\n const state = generateState()\n \n debug('oauth', `Starting OAuth flow on port ${port}`)\n \n // Build authorization URL\n const authParams = new URLSearchParams({\n client_id: OAUTH_CONFIG.clientId,\n redirect_uri: redirectUri,\n response_type: 'code',\n scope: OAUTH_CONFIG.scopes.join(' '),\n access_type: 'offline',\n prompt: 'consent',\n state\n })\n \n const authUrl = `${OAUTH_CONFIG.authUrl}?${authParams.toString()}`\n\n // Manual flow check\n if (options.manual) {\n info('')\n info('MANUAL LOGIN MODE')\n info('1. Copy this URL and open it in your browser:')\n info(authUrl)\n info('')\n info('2. Login with your Google account.')\n info('3. You will be redirected to a localhost URL (which may fail to load).')\n info('4. Copy that ENTIRE localhost URL and paste it below.')\n info('')\n \n const { pastedUrl } = await inquirer.prompt([\n {\n type: 'input',\n name: 'pastedUrl',\n message: 'Paste the full redirect URL here:',\n validate: (input: string) => input.trim().length > 0 ? true : 'Please paste the URL'\n }\n ])\n \n try {\n const url = new URL(pastedUrl.trim())\n const code = url.searchParams.get('code')\n const returnedState = url.searchParams.get('state')\n const errorParam = url.searchParams.get('error')\n \n if (errorParam) {\n return { success: false, error: errorParam }\n }\n \n if (!code || returnedState !== state) {\n return { success: false, error: 'Invalid URL: Missing code or state mismatch' }\n }\n \n return await completeLogin(code, redirectUri)\n } catch (err) {\n if (err instanceof Error) {\n return { success: false, error: err.message }\n }\n return { success: false, error: 'Invalid URL format' }\n }\n }\n \n return new Promise((resolve) => {\n let resolved = false\n \n const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n if (resolved) return\n \n const url = new URL(req.url || '/', `http://127.0.0.1:${port}`)\n \n if (url.pathname === '/callback') {\n const code = url.searchParams.get('code')\n const returnedState = url.searchParams.get('state')\n const errorParam = url.searchParams.get('error')\n \n if (errorParam) {\n res.writeHead(400, { 'Content-Type': 'text/html' })\n res.end('<html><body><h1>Login Failed</h1><p>You can close this window.</p></body></html>')\n resolved = true\n server.close()\n resolve({ success: false, error: errorParam })\n return\n }\n \n if (!code || returnedState !== state) {\n res.writeHead(400, { 'Content-Type': 'text/html' })\n res.end('<html><body><h1>Invalid Request</h1><p>State mismatch or missing code.</p></body></html>')\n resolved = true\n server.close()\n resolve({ success: false, error: 'Invalid callback' })\n return\n }\n \n try {\n // Use common login logic\n const result = await completeLogin(code, redirectUri)\n \n res.writeHead(200, { 'Content-Type': 'text/html' })\n res.end(`\n <html>\n <body style=\"font-family: system-ui; padding: 40px; text-align: center;\">\n <h1>Login Successful!</h1>\n <p>You are now logged in${result.email ? ` as <strong>${result.email}</strong>` : ''}.</p>\n <p>You can close this window and return to the terminal.</p>\n </body>\n </html>\n `)\n \n resolved = true\n server.close()\n resolve(result)\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'text/html' })\n res.end('<html><body><h1>Login Failed</h1><p>Token exchange failed.</p></body></html>')\n resolved = true\n server.close()\n resolve({ success: false, error: err instanceof Error ? err.message : 'Unknown error' })\n }\n }\n })\n \n server.listen(port, '127.0.0.1', async () => {\n info('')\n info('Opening browser for Google login...')\n info('')\n \n if (options.noBrowser) {\n info('Open this URL in your browser:')\n info(authUrl)\n } else {\n try {\n await open(authUrl)\n info('If the browser did not open, visit this URL:')\n info(authUrl)\n } catch (err) {\n debug('oauth', 'Failed to open browser', err)\n info('Could not open browser. Please visit this URL:')\n info(authUrl)\n }\n }\n \n info('')\n info('Waiting for authentication...')\n })\n \n // Timeout after 2 minutes\n setTimeout(() => {\n if (!resolved) {\n resolved = true\n server.close()\n resolve({ success: false, error: 'Login timed out' })\n }\n }, 2 * 60 * 1000)\n })\n}\n\n/**\n * Refresh access token using refresh token\n */\nexport async function refreshAccessToken(refreshToken: string): Promise<OAuthTokenResponse> {\n debug('oauth', 'Refreshing access token')\n \n const params = new URLSearchParams({\n refresh_token: refreshToken,\n client_id: OAUTH_CONFIG.clientId,\n client_secret: OAUTH_CONFIG.clientSecret,\n grant_type: 'refresh_token'\n })\n \n const response = await fetch(OAUTH_CONFIG.tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded'\n },\n body: params.toString()\n })\n \n if (!response.ok) {\n const error = await response.text()\n debug('oauth', 'Token refresh failed', error)\n throw new Error(`Token refresh failed: ${response.status}`)\n }\n \n const data = await response.json() as OAuthTokenResponse\n debug('oauth', 'Token refresh successful')\n return data\n}\n","/**\n * Type definitions for multi-account support\n */\n\nimport type { StoredTokens, QuotaSnapshot } from '../quota/types.js'\n\n/**\n * Global configuration stored in config.json\n */\nexport interface GlobalConfig {\n version: string\n activeAccount: string | null\n preferences: ConfigPreferences\n}\n\n/**\n * User preferences\n */\nexport interface ConfigPreferences {\n cacheTTL: number // seconds, default 300 (5 minutes)\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG: GlobalConfig = {\n version: '2.0',\n activeAccount: null,\n preferences: {\n cacheTTL: 300\n }\n}\n\n/**\n * Per-account metadata stored in metadata.json\n */\nexport interface AccountMetadata {\n email: string\n addedAt: string // ISO date string\n lastUsed: string // ISO date string\n}\n\n/**\n * Cached quota data stored in cache.json\n */\nexport interface CachedQuota {\n cachedAt: string // ISO date string\n ttl: number // seconds\n data: QuotaSnapshot | null\n}\n\n/**\n * Account info returned by account manager\n */\nexport interface AccountInfo {\n email: string\n isActive: boolean\n metadata: AccountMetadata | null\n tokens: StoredTokens | null\n cache: CachedQuota | null\n status: AccountStatus\n}\n\n/**\n * Account status for display\n */\nexport type AccountStatus = 'valid' | 'expired' | 'invalid'\n\n/**\n * Account summary for list display\n */\nexport interface AccountSummary {\n email: string\n isActive: boolean\n status: AccountStatus\n lastUsed: string | null\n cachedCredits?: {\n used: number\n limit: number\n } | null\n}\n","/**\n * Account storage - file-based operations for multi-account\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, rmSync } from 'node:fs'\nimport { join, basename } from 'node:path'\nimport { getAccountsDir, getAccountDir } from '../core/env.js'\nimport { debug } from '../core/logger.js'\nimport type { StoredTokens } from '../quota/types.js'\nimport type { AccountMetadata, CachedQuota } from './types.js'\n\n/**\n * Ensure accounts directory exists\n */\nexport function ensureAccountsDir(): void {\n const dir = getAccountsDir()\n if (!existsSync(dir)) {\n debug('accounts-storage', `Creating accounts directory: ${dir}`)\n mkdirSync(dir, { recursive: true })\n }\n}\n\n/**\n * Ensure specific account directory exists\n */\nexport function ensureAccountDir(email: string): void {\n ensureAccountsDir()\n const dir = getAccountDir(email)\n if (!existsSync(dir)) {\n debug('accounts-storage', `Creating account directory: ${dir}`)\n mkdirSync(dir, { recursive: true })\n }\n}\n\n/**\n * Check if an account exists\n */\nexport function accountExists(email: string): boolean {\n const dir = getAccountDir(email)\n return existsSync(dir) && existsSync(join(dir, 'tokens.json'))\n}\n\n/**\n * List all account directories (by email)\n */\nexport function listAccountEmails(): string[] {\n const accountsDir = getAccountsDir()\n \n if (!existsSync(accountsDir)) {\n return []\n }\n \n try {\n const entries = readdirSync(accountsDir, { withFileTypes: true })\n const emails: string[] = []\n \n for (const entry of entries) {\n if (entry.isDirectory()) {\n // Check if it has a tokens.json file\n const tokensPath = join(accountsDir, entry.name, 'tokens.json')\n if (existsSync(tokensPath)) {\n emails.push(entry.name)\n }\n }\n }\n \n return emails\n } catch (err) {\n debug('accounts-storage', 'Failed to list accounts', err)\n return []\n }\n}\n\n// ============================================================\n// Token operations\n// ============================================================\n\n/**\n * Save tokens for an account\n */\nexport function saveAccountTokens(email: string, tokens: StoredTokens): void {\n ensureAccountDir(email)\n const path = join(getAccountDir(email), 'tokens.json')\n \n debug('accounts-storage', `Saving tokens for ${email}`)\n writeFileSync(path, JSON.stringify(tokens, null, 2), { mode: 0o600 })\n}\n\n/**\n * Load tokens for an account\n */\nexport function loadAccountTokens(email: string): StoredTokens | null {\n const path = join(getAccountDir(email), 'tokens.json')\n \n if (!existsSync(path)) {\n debug('accounts-storage', `No tokens file for ${email}`)\n return null\n }\n \n try {\n const content = readFileSync(path, 'utf-8')\n return JSON.parse(content) as StoredTokens\n } catch (err) {\n debug('accounts-storage', `Failed to parse tokens for ${email}`, err)\n return null\n }\n}\n\n// ============================================================\n// Metadata operations\n// ============================================================\n\n/**\n * Save metadata for an account\n */\nexport function saveAccountMetadata(email: string, metadata: AccountMetadata): void {\n ensureAccountDir(email)\n const path = join(getAccountDir(email), 'metadata.json')\n \n debug('accounts-storage', `Saving metadata for ${email}`)\n writeFileSync(path, JSON.stringify(metadata, null, 2), { mode: 0o600 })\n}\n\n/**\n * Load metadata for an account\n */\nexport function loadAccountMetadata(email: string): AccountMetadata | null {\n const path = join(getAccountDir(email), 'metadata.json')\n \n if (!existsSync(path)) {\n return null\n }\n \n try {\n const content = readFileSync(path, 'utf-8')\n return JSON.parse(content) as AccountMetadata\n } catch (err) {\n debug('accounts-storage', `Failed to parse metadata for ${email}`, err)\n return null\n }\n}\n\n/**\n * Update lastUsed timestamp for an account\n */\nexport function updateLastUsed(email: string): void {\n const metadata = loadAccountMetadata(email)\n if (metadata) {\n metadata.lastUsed = new Date().toISOString()\n saveAccountMetadata(email, metadata)\n }\n}\n\n// ============================================================\n// Cache operations\n// ============================================================\n\n/**\n * Save cached quota for an account\n */\nexport function saveAccountCache(email: string, cache: CachedQuota): void {\n ensureAccountDir(email)\n const path = join(getAccountDir(email), 'cache.json')\n \n debug('accounts-storage', `Saving cache for ${email}`)\n writeFileSync(path, JSON.stringify(cache, null, 2))\n}\n\n/**\n * Load cached quota for an account\n */\nexport function loadAccountCache(email: string): CachedQuota | null {\n const path = join(getAccountDir(email), 'cache.json')\n \n if (!existsSync(path)) {\n return null\n }\n \n try {\n const content = readFileSync(path, 'utf-8')\n return JSON.parse(content) as CachedQuota\n } catch (err) {\n debug('accounts-storage', `Failed to parse cache for ${email}`, err)\n return null\n }\n}\n\n/**\n * Delete cache for an account\n */\nexport function deleteAccountCache(email: string): void {\n const path = join(getAccountDir(email), 'cache.json')\n \n if (existsSync(path)) {\n try {\n rmSync(path)\n debug('accounts-storage', `Deleted cache for ${email}`)\n } catch (err) {\n debug('accounts-storage', `Failed to delete cache for ${email}`, err)\n }\n }\n}\n\n// ============================================================\n// Account deletion\n// ============================================================\n\n/**\n * Delete an account and all its data\n */\nexport function deleteAccount(email: string): boolean {\n const dir = getAccountDir(email)\n \n if (!existsSync(dir)) {\n debug('accounts-storage', `Account ${email} does not exist`)\n return false\n }\n \n try {\n rmSync(dir, { recursive: true, force: true })\n debug('accounts-storage', `Deleted account ${email}`)\n return true\n } catch (err) {\n debug('accounts-storage', `Failed to delete account ${email}`, err)\n return false\n }\n}\n","/**\n * Environment and platform utilities\n */\n\nimport { homedir, platform } from 'node:os'\nimport { join } from 'node:path'\n\nexport type Platform = 'windows' | 'macos' | 'linux'\n\n/**\n * Get the current platform\n */\nexport function getPlatform(): Platform {\n const p = platform()\n if (p === 'win32') return 'windows'\n if (p === 'darwin') return 'macos'\n return 'linux'\n}\n\n/**\n * Get the config directory for this application\n * - Windows: %APPDATA%/antigravity-usage\n * - macOS: ~/Library/Application Support/antigravity-usage\n * - Linux: ~/.config/antigravity-usage\n */\nexport function getConfigDir(): string {\n const p = getPlatform()\n const home = homedir()\n \n switch (p) {\n case 'windows':\n return join(process.env.APPDATA || join(home, 'AppData', 'Roaming'), 'antigravity-usage')\n case 'macos':\n return join(home, 'Library', 'Application Support', 'antigravity-usage')\n case 'linux':\n default:\n return join(process.env.XDG_CONFIG_HOME || join(home, '.config'), 'antigravity-usage')\n }\n}\n\n/**\n * Get the path to the tokens file (legacy - single account)\n */\nexport function getTokensPath(): string {\n return join(getConfigDir(), 'tokens.json')\n}\n\n/**\n * Get the accounts directory\n */\nexport function getAccountsDir(): string {\n return join(getConfigDir(), 'accounts')\n}\n\n/**\n * Get the directory for a specific account\n * @param email Account email address\n */\nexport function getAccountDir(email: string): string {\n // Sanitize email for filesystem (replace special chars)\n const safeName = email.replace(/[^a-zA-Z0-9@._-]/g, '_')\n return join(getAccountsDir(), safeName)\n}\n\n/**\n * Get the path to global config file\n */\nexport function getGlobalConfigPath(): string {\n return join(getConfigDir(), 'config.json')\n}\n","/**\n * Global configuration management\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { getGlobalConfigPath, getConfigDir } from '../core/env.js'\nimport { debug } from '../core/logger.js'\nimport { DEFAULT_CONFIG, type GlobalConfig } from './types.js'\n\n/**\n * Load global config from disk\n */\nexport function loadConfig(): GlobalConfig {\n const path = getGlobalConfigPath()\n \n if (!existsSync(path)) {\n debug('config', 'No config file found, using defaults')\n return { ...DEFAULT_CONFIG }\n }\n \n try {\n const content = readFileSync(path, 'utf-8')\n const config = JSON.parse(content) as Partial<GlobalConfig>\n \n // Merge with defaults to ensure all fields exist\n return {\n ...DEFAULT_CONFIG,\n ...config,\n preferences: {\n ...DEFAULT_CONFIG.preferences,\n ...config.preferences\n }\n }\n } catch (err) {\n debug('config', 'Failed to parse config, using defaults', err)\n return { ...DEFAULT_CONFIG }\n }\n}\n\n/**\n * Save global config to disk\n */\nexport function saveConfig(config: GlobalConfig): void {\n const path = getGlobalConfigPath()\n const dir = dirname(path)\n \n // Ensure directory exists\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n \n debug('config', `Saving config to ${path}`)\n writeFileSync(path, JSON.stringify(config, null, 2))\n}\n\n/**\n * Get the active account email\n */\nexport function getActiveAccountEmail(): string | null {\n const config = loadConfig()\n return config.activeAccount\n}\n\n/**\n * Set the active account email\n */\nexport function setActiveAccountEmail(email: string | null): void {\n const config = loadConfig()\n config.activeAccount = email\n saveConfig(config)\n}\n\n/**\n * Get cache TTL in seconds\n */\nexport function getCacheTTL(): number {\n const config = loadConfig()\n return config.preferences.cacheTTL\n}\n","/**\n * Cache management for quota data\n */\n\nimport { loadAccountCache, saveAccountCache, deleteAccountCache } from './storage.js'\nimport { getCacheTTL } from './config.js'\nimport { debug } from '../core/logger.js'\nimport type { QuotaSnapshot } from '../quota/types.js'\nimport type { CachedQuota } from './types.js'\n\n/**\n * Check if cache is valid for an account\n */\nexport function isCacheValid(email: string): boolean {\n const cache = loadAccountCache(email)\n \n if (!cache || !cache.data) {\n debug('cache', `No valid cache for ${email}`)\n return false\n }\n \n const cachedAt = new Date(cache.cachedAt).getTime()\n const ttlMs = cache.ttl * 1000\n const now = Date.now()\n \n const isValid = (now - cachedAt) < ttlMs\n debug('cache', `Cache for ${email} is ${isValid ? 'valid' : 'stale'}`)\n \n return isValid\n}\n\n/**\n * Get cache age in seconds\n */\nexport function getCacheAge(email: string): number | null {\n const cache = loadAccountCache(email)\n \n if (!cache) {\n return null\n }\n \n const cachedAt = new Date(cache.cachedAt).getTime()\n return Math.floor((Date.now() - cachedAt) / 1000)\n}\n\n/**\n * Save quota data to cache\n */\nexport function saveCache(email: string, data: QuotaSnapshot): void {\n const ttl = getCacheTTL()\n \n const cache: CachedQuota = {\n cachedAt: new Date().toISOString(),\n ttl,\n data\n }\n \n saveAccountCache(email, cache)\n debug('cache', `Cached quota for ${email}, TTL: ${ttl}s`)\n}\n\n/**\n * Load cached quota data\n */\nexport function loadCache(email: string): QuotaSnapshot | null {\n const cache = loadAccountCache(email)\n return cache?.data || null\n}\n\n/**\n * Load cache with metadata\n */\nexport function loadCacheWithMeta(email: string): CachedQuota | null {\n return loadAccountCache(email)\n}\n\n/**\n * Invalidate cache for an account\n */\nexport function invalidateCache(email: string): void {\n deleteAccountCache(email)\n debug('cache', `Invalidated cache for ${email}`)\n}\n","/**\n * Account manager - orchestrates multi-account operations\n */\n\nimport { debug } from '../core/logger.js'\nimport { \n listAccountEmails, \n loadAccountTokens, \n saveAccountTokens,\n loadAccountMetadata,\n saveAccountMetadata,\n accountExists,\n deleteAccount as deleteAccountDir,\n updateLastUsed\n} from './storage.js'\nimport { \n getActiveAccountEmail, \n setActiveAccountEmail \n} from './config.js'\nimport { \n isCacheValid, \n loadCacheWithMeta,\n getCacheAge\n} from './cache.js'\nimport type { StoredTokens } from '../quota/types.js'\nimport type { \n AccountInfo, \n AccountMetadata, \n AccountStatus, \n AccountSummary \n} from './types.js'\n\n// Refresh token 5 minutes before expiry\nconst EXPIRY_BUFFER_MS = 5 * 60 * 1000\n\n/**\n * Account Manager - singleton class for managing multiple accounts\n */\nexport class AccountManager {\n private static instance: AccountManager | null = null\n \n private constructor() {}\n \n static getInstance(): AccountManager {\n if (!AccountManager.instance) {\n AccountManager.instance = new AccountManager()\n }\n return AccountManager.instance\n }\n \n /**\n * Reset instance (for testing)\n */\n static resetInstance(): void {\n AccountManager.instance = null\n }\n \n /**\n * Get all account emails\n */\n getAccountEmails(): string[] {\n return listAccountEmails()\n }\n \n /**\n * Get active account email\n */\n getActiveEmail(): string | null {\n return getActiveAccountEmail()\n }\n \n /**\n * Set active account\n */\n setActiveAccount(email: string): boolean {\n if (!accountExists(email)) {\n debug('account-manager', `Account ${email} does not exist`)\n return false\n }\n \n setActiveAccountEmail(email)\n updateLastUsed(email)\n debug('account-manager', `Switched to account ${email}`)\n return true\n }\n \n /**\n * Check if an account exists\n */\n hasAccount(email: string): boolean {\n return accountExists(email)\n }\n \n /**\n * Get account status\n */\n getAccountStatus(email: string): AccountStatus {\n const tokens = loadAccountTokens(email)\n \n if (!tokens) {\n return 'invalid'\n }\n \n // Check if token is expired\n const now = Date.now()\n if (now >= tokens.expiresAt - EXPIRY_BUFFER_MS) {\n // Expired, but might have refresh token\n if (tokens.refreshToken) {\n return 'expired' // Can be refreshed\n }\n return 'invalid'\n }\n \n return 'valid'\n }\n \n /**\n * Get detailed account info\n */\n getAccountInfo(email: string): AccountInfo | null {\n if (!accountExists(email)) {\n return null\n }\n \n const activeEmail = getActiveAccountEmail()\n const tokens = loadAccountTokens(email)\n const metadata = loadAccountMetadata(email)\n const cache = loadCacheWithMeta(email)\n const status = this.getAccountStatus(email)\n \n return {\n email,\n isActive: email === activeEmail,\n tokens,\n metadata,\n cache,\n status\n }\n }\n \n /**\n * Get account summaries for list display\n */\n getAccountSummaries(): AccountSummary[] {\n const emails = this.getAccountEmails()\n const activeEmail = getActiveAccountEmail()\n \n return emails.map(email => {\n const metadata = loadAccountMetadata(email)\n const cache = loadCacheWithMeta(email)\n const status = this.getAccountStatus(email)\n \n // Extract credits from cache if available\n let cachedCredits: { used: number; limit: number } | null = null\n if (cache?.data?.promptCredits) {\n const pc = cache.data.promptCredits\n cachedCredits = {\n used: pc.monthly - pc.available,\n limit: pc.monthly\n }\n }\n \n return {\n email,\n isActive: email === activeEmail,\n status,\n lastUsed: metadata?.lastUsed || null,\n cachedCredits\n }\n })\n }\n \n /**\n * Add a new account after successful OAuth\n */\n addAccount(tokens: StoredTokens, email: string): void {\n debug('account-manager', `Adding account ${email}`)\n \n // Save tokens\n saveAccountTokens(email, tokens)\n \n // Create metadata\n const now = new Date().toISOString()\n const metadata: AccountMetadata = {\n email,\n addedAt: now,\n lastUsed: now\n }\n saveAccountMetadata(email, metadata)\n \n // Set as active account\n setActiveAccountEmail(email)\n \n debug('account-manager', `Account ${email} added and set as active`)\n }\n \n /**\n * Update tokens for existing account\n */\n updateTokens(email: string, tokens: StoredTokens): void {\n if (!accountExists(email)) {\n debug('account-manager', `Cannot update tokens: account ${email} does not exist`)\n return\n }\n \n saveAccountTokens(email, tokens)\n updateLastUsed(email)\n debug('account-manager', `Updated tokens for ${email}`)\n }\n \n /**\n * Remove an account\n */\n removeAccount(email: string): boolean {\n if (!accountExists(email)) {\n debug('account-manager', `Account ${email} does not exist`)\n return false\n }\n \n // If removing active account, clear active\n const activeEmail = getActiveAccountEmail()\n if (email === activeEmail) {\n setActiveAccountEmail(null)\n }\n \n const deleted = deleteAccountDir(email)\n \n // If we deleted the active and there are other accounts, set first as active\n if (deleted && email === activeEmail) {\n const remaining = this.getAccountEmails()\n if (remaining.length > 0) {\n setActiveAccountEmail(remaining[0])\n debug('account-manager', `Set ${remaining[0]} as new active account`)\n }\n }\n \n return deleted\n }\n \n /**\n * Remove all accounts\n */\n removeAllAccounts(): number {\n const emails = this.getAccountEmails()\n let count = 0\n \n for (const email of emails) {\n if (deleteAccountDir(email)) {\n count++\n }\n }\n \n setActiveAccountEmail(null)\n debug('account-manager', `Removed ${count} accounts`)\n \n return count\n }\n \n /**\n * Get tokens for an account\n */\n getTokens(email: string): StoredTokens | null {\n return loadAccountTokens(email)\n }\n \n /**\n * Get tokens for active account\n */\n getActiveTokens(): StoredTokens | null {\n const email = getActiveAccountEmail()\n if (!email) {\n return null\n }\n return loadAccountTokens(email)\n }\n \n /**\n * Check if cache is valid for an account\n */\n isCacheValid(email: string): boolean {\n return isCacheValid(email)\n }\n \n /**\n * Get cache age in seconds\n */\n getCacheAge(email: string): number | null {\n return getCacheAge(email)\n }\n}\n\n/**\n * Get account manager instance\n */\nexport function getAccountManager(): AccountManager {\n return AccountManager.getInstance()\n}\n","/**\n * Token storage - file-based implementation\n * \n * This module provides backward-compatible token storage.\n * It routes to the active account in the new multi-account structure.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { getTokensPath, getConfigDir, getAccountDir } from '../core/env.js'\nimport { debug } from '../core/logger.js'\nimport { \n getActiveAccountEmail,\n setActiveAccountEmail\n} from '../accounts/config.js'\nimport {\n saveAccountTokens,\n loadAccountTokens,\n deleteAccount,\n accountExists\n} from '../accounts/storage.js'\nimport type { StoredTokens } from '../quota/types.js'\n\n/**\n * Save tokens to disk\n * Routes to active account in multi-account structure\n */\nexport function saveTokens(tokens: StoredTokens): void {\n const email = tokens.email\n \n if (!email) {\n // Fallback to legacy storage if no email\n const path = getTokensPath()\n const dir = dirname(path)\n \n debug('storage', `Saving tokens to legacy path ${path}`)\n \n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n \n writeFileSync(path, JSON.stringify(tokens, null, 2), { mode: 0o600 })\n return\n }\n \n // Use multi-account storage\n debug('storage', `Saving tokens for account ${email}`)\n saveAccountTokens(email, tokens)\n \n // Set as active if no active account\n if (!getActiveAccountEmail()) {\n setActiveAccountEmail(email)\n }\n}\n\n/**\n * Load tokens from disk\n * First tries active account, then falls back to legacy path\n */\nexport function loadTokens(): StoredTokens | null {\n // Try active account first\n const activeEmail = getActiveAccountEmail()\n \n if (activeEmail) {\n const tokens = loadAccountTokens(activeEmail)\n if (tokens) {\n debug('storage', `Loaded tokens for active account ${activeEmail}`)\n return tokens\n }\n }\n \n // Fallback to legacy path\n const legacyPath = getTokensPath()\n \n debug('storage', `Loading tokens from legacy path ${legacyPath}`)\n \n if (!existsSync(legacyPath)) {\n debug('storage', 'No tokens file found')\n return null\n }\n \n try {\n const content = readFileSync(legacyPath, 'utf-8')\n const tokens = JSON.parse(content) as StoredTokens\n debug('storage', 'Tokens loaded successfully from legacy path')\n return tokens\n } catch (err) {\n debug('storage', 'Failed to parse tokens file', err)\n return null\n }\n}\n\n/**\n * Delete stored tokens\n * Removes active account in multi-account structure\n */\nexport function deleteTokens(): boolean {\n const activeEmail = getActiveAccountEmail()\n \n if (activeEmail && accountExists(activeEmail)) {\n debug('storage', `Deleting account ${activeEmail}`)\n return deleteAccount(activeEmail)\n }\n \n // Fallback to legacy path\n const path = getTokensPath()\n \n debug('storage', `Deleting tokens at legacy path ${path}`)\n \n if (!existsSync(path)) {\n debug('storage', 'No tokens file to delete')\n return false\n }\n \n try {\n unlinkSync(path)\n debug('storage', 'Tokens deleted successfully')\n return true\n } catch (err) {\n debug('storage', 'Failed to delete tokens', err)\n return false\n }\n}\n\n/**\n * Check if tokens exist\n */\nexport function hasTokens(): boolean {\n // Check active account\n const activeEmail = getActiveAccountEmail()\n if (activeEmail && accountExists(activeEmail)) {\n return true\n }\n \n // Fallback to legacy\n return existsSync(getTokensPath())\n}\n\n/**\n * Get config directory info for doctor command\n */\nexport function getStorageInfo(): { configDir: string; tokensPath: string; exists: boolean } {\n const configDir = getConfigDir()\n const activeEmail = getActiveAccountEmail()\n \n // Prefer active account path\n let tokensPath: string\n let exists: boolean\n \n if (activeEmail) {\n tokensPath = `${getAccountDir(activeEmail)}/tokens.json`\n exists = accountExists(activeEmail)\n } else {\n tokensPath = getTokensPath()\n exists = existsSync(tokensPath)\n }\n \n return {\n configDir,\n tokensPath,\n exists\n }\n}\n","/**\n * Custom error classes for antigravity-usage CLI\n */\n\nexport class NotLoggedInError extends Error {\n constructor(message = 'Not logged in. Run: antigravity-usage login') {\n super(message)\n this.name = 'NotLoggedInError'\n }\n}\n\nexport class AuthenticationError extends Error {\n constructor(message = 'Authentication failed. Please login again.') {\n super(message)\n this.name = 'AuthenticationError'\n }\n}\n\nexport class NetworkError extends Error {\n constructor(message = 'Network error. Please check your connection.') {\n super(message)\n this.name = 'NetworkError'\n }\n}\n\nexport class RateLimitError extends Error {\n retryAfterMs?: number\n\n constructor(message = 'Rate limited. Please try again later.', retryAfterMs?: number) {\n super(message)\n this.name = 'RateLimitError'\n this.retryAfterMs = retryAfterMs\n }\n}\n\nexport class APIError extends Error {\n statusCode?: number\n \n constructor(message: string, statusCode?: number) {\n super(message)\n this.name = 'APIError'\n this.statusCode = statusCode\n }\n}\n\nexport class TokenRefreshError extends Error {\n /** Original error that caused the refresh failure */\n cause?: Error\n /** HTTP status code if available */\n statusCode?: number\n /** Whether the error is retryable (network issues) vs permanent (invalid token) */\n isRetryable: boolean\n \n constructor(\n message = 'Failed to refresh token. Please login again.',\n options?: {\n cause?: Error\n statusCode?: number\n isRetryable?: boolean\n }\n ) {\n super(message)\n this.name = 'TokenRefreshError'\n this.cause = options?.cause\n this.statusCode = options?.statusCode\n // Default: retryable unless we get a 400/401 (invalid_grant, etc.)\n this.isRetryable = options?.isRetryable ?? true\n }\n \n /** Get detailed error message including cause */\n getDetailedMessage(): string {\n let msg = this.message\n if (this.statusCode) {\n msg += ` (HTTP ${this.statusCode})`\n }\n if (this.cause) {\n msg += `: ${this.cause.message}`\n }\n return msg\n }\n}\n\nexport class AntigravityNotRunningError extends Error {\n constructor(message = 'Antigravity language server is not running. Please start Antigravity in your IDE.') {\n super(message)\n this.name = 'AntigravityNotRunningError'\n }\n}\n\nexport class LocalConnectionError extends Error {\n constructor(message = 'Failed to connect to local Antigravity server.') {\n super(message)\n this.name = 'LocalConnectionError'\n }\n}\n\nexport class PortDetectionError extends Error {\n constructor(message = 'Could not detect Antigravity server port.') {\n super(message)\n this.name = 'PortDetectionError'\n }\n}\n\nexport class NoAuthMethodAvailableError extends Error {\n constructor(message = 'Unable to fetch quota: Antigravity is not running and you are not logged in.\\n\\nPlease do one of the following:\\n • Run Antigravity in your IDE (VSCode, etc.), or\\n • Login with: antigravity-usage login') {\n super(message)\n this.name = 'NoAuthMethodAvailableError'\n }\n}\n\n","/**\n * Token manager with automatic refresh\n * \n * Updated for multi-account support - can manage tokens for specific accounts\n * or default to the active account.\n */\n\nimport { loadTokens, saveTokens, hasTokens } from './storage.js'\nimport { refreshAccessToken } from './oauth.js'\nimport { debug } from '../core/logger.js'\nimport { NotLoggedInError, TokenRefreshError } from '../core/errors.js'\nimport { \n getActiveAccountEmail,\n loadAccountTokens,\n saveAccountTokens,\n accountExists,\n updateLastUsed\n} from '../accounts/index.js'\nimport type { StoredTokens } from '../quota/types.js'\n\n// Refresh token 5 minutes before expiry\nconst EXPIRY_BUFFER_MS = 5 * 60 * 1000\n\n/**\n * Token manager class for handling authentication\n * Can work with active account or a specific account email\n */\nexport class TokenManager {\n private tokens: StoredTokens | null = null\n private accountEmail: string | null = null\n \n constructor(email?: string) {\n if (email) {\n // Specific account requested\n this.accountEmail = email\n this.tokens = loadAccountTokens(email)\n } else {\n // Use active account\n this.accountEmail = getActiveAccountEmail()\n \n // If we have an active account email, use account-specific storage\n // Otherwise fall back to legacy default storage\n if (this.accountEmail) {\n this.tokens = loadAccountTokens(this.accountEmail)\n } else {\n this.tokens = loadTokens()\n }\n }\n }\n \n /**\n * Get the email this manager is for\n */\n getAccountEmail(): string | null {\n return this.accountEmail || this.tokens?.email || null\n }\n \n /**\n * Check if user is logged in (has tokens)\n */\n isLoggedIn(): boolean {\n if (this.accountEmail) {\n return accountExists(this.accountEmail) && this.tokens !== null\n }\n return hasTokens() && this.tokens !== null\n }\n \n /**\n * Get the stored email\n */\n getEmail(): string | undefined {\n return this.tokens?.email\n }\n \n /**\n * Get token expiry time\n */\n getExpiresAt(): Date | undefined {\n if (!this.tokens) return undefined\n return new Date(this.tokens.expiresAt)\n }\n \n /**\n * Get stored project ID\n */\n getProjectId(): string | undefined {\n return this.tokens?.projectId\n }\n \n /**\n * Set and persist project ID\n */\n setProjectId(projectId: string): void {\n if (!this.tokens) return\n \n this.tokens.projectId = projectId\n \n // Save to disk\n if (this.accountEmail) {\n saveAccountTokens(this.accountEmail, this.tokens)\n } else {\n saveTokens(this.tokens)\n }\n \n debug('token-manager', `Project ID saved: ${projectId}`)\n }\n \n /**\n * Check if token is expired or about to expire\n */\n isTokenExpired(): boolean {\n if (!this.tokens) return true\n return Date.now() >= this.tokens.expiresAt - EXPIRY_BUFFER_MS\n }\n \n /**\n * Get a valid access token, refreshing if necessary\n */\n async getValidAccessToken(): Promise<string> {\n if (!this.tokens) {\n throw new NotLoggedInError()\n }\n \n debug('token-manager', 'Checking token validity')\n \n // Check if token needs refresh\n if (this.isTokenExpired()) {\n debug('token-manager', 'Token expired or expiring soon, refreshing...')\n await this.refreshToken()\n }\n \n return this.tokens.accessToken\n }\n \n /**\n * Refresh the access token with retry logic\n * Retries on transient network errors, fails immediately on permanent errors (invalid_grant)\n */\n async refreshToken(): Promise<void> {\n if (!this.tokens?.refreshToken) {\n throw new NotLoggedInError('No refresh token available. Please login again.')\n }\n \n const MAX_RETRIES = 3\n const BASE_DELAY_MS = 1000 // 1s, 2s, 4s exponential backoff\n \n let lastError: Error | undefined\n \n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n try {\n debug('token-manager', `Refreshing token (attempt ${attempt}/${MAX_RETRIES})...`)\n const response = await refreshAccessToken(this.tokens.refreshToken)\n \n // Update tokens\n this.tokens = {\n accessToken: response.access_token,\n refreshToken: response.refresh_token || this.tokens.refreshToken,\n expiresAt: Date.now() + response.expires_in * 1000,\n email: this.tokens.email,\n projectId: this.tokens.projectId\n }\n \n // Save to disk\n if (this.accountEmail) {\n saveAccountTokens(this.accountEmail, this.tokens)\n updateLastUsed(this.accountEmail)\n } else {\n saveTokens(this.tokens)\n }\n \n debug('token-manager', 'Token refreshed successfully')\n return // Success!\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err))\n \n // Check if this is a permanent error (don't retry)\n const errorMessage = lastError.message.toLowerCase()\n const isPermanentError = \n errorMessage.includes('invalid_grant') ||\n errorMessage.includes('400') ||\n errorMessage.includes('401') ||\n errorMessage.includes('invalid_token') ||\n errorMessage.includes('token has been revoked')\n \n if (isPermanentError) {\n debug('token-manager', `Token refresh failed permanently: ${lastError.message}`)\n throw new TokenRefreshError(\n `Refresh token invalid or expired. Please login again.`,\n { cause: lastError, isRetryable: false }\n )\n }\n \n // Transient error - retry with exponential backoff\n if (attempt < MAX_RETRIES) {\n const delayMs = BASE_DELAY_MS * Math.pow(2, attempt - 1)\n debug('token-manager', `Token refresh attempt ${attempt} failed: ${lastError.message}. Retrying in ${delayMs}ms...`)\n await this.sleep(delayMs)\n } else {\n debug('token-manager', `Token refresh failed after ${MAX_RETRIES} attempts: ${lastError.message}`)\n }\n }\n }\n \n // All retries exhausted\n throw new TokenRefreshError(\n `Failed to refresh token after ${MAX_RETRIES} attempts`,\n { cause: lastError, isRetryable: true }\n )\n }\n \n /**\n * Sleep helper for retry delays\n */\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n }\n \n /**\n * Reload tokens from disk\n */\n reload(): void {\n if (this.accountEmail) {\n this.tokens = loadAccountTokens(this.accountEmail)\n } else {\n this.tokens = loadTokens()\n }\n }\n}\n\n// Singleton instance for default (active account) manager\nlet tokenManagerInstance: TokenManager | null = null\n\n/**\n * Get the token manager instance for active account\n */\nexport function getTokenManager(): TokenManager {\n if (!tokenManagerInstance) {\n tokenManagerInstance = new TokenManager()\n }\n return tokenManagerInstance\n}\n\n/**\n * Get token manager for a specific account\n */\nexport function getTokenManagerForAccount(email: string): TokenManager {\n return new TokenManager(email)\n}\n\n/**\n * Reset the token manager (for testing or after account changes)\n */\nexport function resetTokenManager(): void {\n tokenManagerInstance = null\n}\n","/**\n * Login command - authenticate with Google\n * \n * This is kept for backward compatibility.\n * For multi-account management, use `antigravity-usage accounts add`\n */\n\nimport { startOAuthFlow } from '../google/oauth.js'\nimport { getAccountManager } from '../accounts/index.js'\nimport { success, error as logError, info } from '../core/logger.js'\nimport { resetTokenManager } from '../google/token-manager.js'\n\ninterface LoginOptions {\n noBrowser?: boolean\n port?: number\n manual?: boolean\n}\n\nexport async function loginCommand(options: LoginOptions): Promise<void> {\n const manager = getAccountManager()\n const existingAccounts = manager.getAccountEmails()\n \n if (existingAccounts.length > 0) {\n info(`You have ${existingAccounts.length} account(s). Adding another account...`)\n }\n \n const result = await startOAuthFlow({\n noBrowser: options.noBrowser,\n port: options.port,\n manual: options.manual\n })\n \n if (result.success) {\n // Reset token manager to pick up new active account\n resetTokenManager()\n \n success(`Logged in successfully${result.email ? ` as ${result.email}` : ''}!`)\n \n const accounts = manager.getAccountEmails()\n if (accounts.length > 1) {\n info(`\\nYou now have ${accounts.length} accounts. Use \\`antigravity-usage accounts list\\` to see all.`)\n }\n \n process.exit(0)\n } else {\n logError(`Login failed: ${result.error}`)\n process.exit(1)\n }\n}\n","/**\n * Logout command - remove account(s)\n */\n\nimport { getAccountManager } from '../accounts/index.js'\nimport { resetTokenManager } from '../google/token-manager.js'\nimport { success, warn, info } from '../core/logger.js'\n\ninterface LogoutOptions {\n all?: boolean\n}\n\nexport function logoutCommand(options: LogoutOptions, email?: string): void {\n const manager = getAccountManager()\n \n // Logout all accounts\n if (options.all) {\n const count = manager.removeAllAccounts()\n resetTokenManager()\n \n if (count > 0) {\n success(`Logged out of ${count} account(s).`)\n } else {\n warn('No accounts to log out.')\n }\n return\n }\n \n // Logout specific account\n if (email) {\n if (!manager.hasAccount(email)) {\n warn(`Account '${email}' not found.`)\n return\n }\n \n const removed = manager.removeAccount(email)\n resetTokenManager()\n \n if (removed) {\n success(`Logged out of ${email}.`)\n \n const remaining = manager.getAccountEmails()\n if (remaining.length > 0) {\n info(`Active account: ${manager.getActiveEmail() || 'none'}`)\n }\n } else {\n warn(`Could not log out of ${email}.`)\n }\n return\n }\n \n // Logout active account (default behavior)\n const activeEmail = manager.getActiveEmail()\n \n if (!activeEmail) {\n warn('Not logged in.')\n return\n }\n \n const removed = manager.removeAccount(activeEmail)\n resetTokenManager()\n \n if (removed) {\n success(`Logged out of ${activeEmail}.`)\n \n const remaining = manager.getAccountEmails()\n if (remaining.length > 0) {\n const newActive = manager.getActiveEmail()\n info(`Switched to: ${newActive}`)\n }\n } else {\n warn('Could not delete account.')\n }\n}\n","/**\n * Token masking utility\n */\n\n/**\n * Mask a token for display, showing first 6 and last 4 characters\n * @example maskToken('abc123xyz789secret') => 'abc123...cret'\n */\nexport function maskToken(token: string): string {\n if (!token) return ''\n if (token.length <= 10) return '***'\n \n const first = token.slice(0, 6)\n const last = token.slice(-4)\n return `${first}...${last}`\n}\n\n/**\n * Mask an email for display\n * @example maskEmail('user@example.com') => 'us**@example.com'\n */\nexport function maskEmail(email: string): string {\n if (!email) return ''\n \n const [local, domain] = email.split('@')\n if (!domain) return email\n \n if (local.length <= 2) {\n return `${local[0] || ''}**@${domain}`\n }\n \n return `${local.slice(0, 2)}**@${domain}`\n}\n","/**\n * Status command - show current login status\n */\n\nimport { getTokenManager, getTokenManagerForAccount } from '../google/token-manager.js'\nimport { getAccountManager } from '../accounts/index.js'\nimport { maskEmail, maskToken } from '../core/mask.js'\nimport { info, warn } from '../core/logger.js'\nimport { isDebugMode } from '../core/logger.js'\nimport Table from 'cli-table3'\n\ninterface StatusOptions {\n all?: boolean\n account?: string\n}\n\n/**\n * Show status for a single account\n */\nfunction showSingleAccountStatus(email?: string): void {\n const tokenManager = email \n ? getTokenManagerForAccount(email)\n : getTokenManager()\n \n console.log()\n console.log('📍 Antigravity Usage Status')\n console.log('─'.repeat(40))\n \n if (!tokenManager.isLoggedIn()) {\n warn('Not logged in')\n console.log()\n info('Run `antigravity-usage login` to authenticate.')\n console.log()\n return\n }\n \n const accountEmail = tokenManager.getEmail()\n const expiresAt = tokenManager.getExpiresAt()\n const isExpired = tokenManager.isTokenExpired()\n \n console.log(`✅ Logged in: Yes`)\n \n if (accountEmail) {\n console.log(`📧 Email: ${maskEmail(accountEmail)}`)\n }\n \n if (expiresAt) {\n const expiryStr = expiresAt.toLocaleString()\n const status = isExpired ? ' (expired/expiring soon)' : ''\n console.log(`⏰ Token expires: ${expiryStr}${status}`)\n }\n \n // Debug mode shows more detail\n if (isDebugMode()) {\n const tokens = email \n ? getAccountManager().getTokens(email)\n : getAccountManager().getActiveTokens()\n if (tokens) {\n console.log()\n console.log('Debug info:')\n console.log(` Access token: ${maskToken(tokens.accessToken)}`)\n console.log(` Refresh token: ${maskToken(tokens.refreshToken)}`)\n }\n }\n \n console.log()\n}\n\n/**\n * Show status for all accounts\n */\nfunction showAllAccountsStatus(): void {\n const manager = getAccountManager()\n const emails = manager.getAccountEmails()\n const activeEmail = manager.getActiveEmail()\n \n console.log()\n console.log('📍 Antigravity Usage Status - All Accounts')\n console.log('═'.repeat(60))\n \n if (emails.length === 0) {\n warn('No accounts found.')\n console.log()\n info('Run `antigravity-usage login` to add an account.')\n console.log()\n return\n }\n \n const table = new Table({\n head: ['Account', 'Logged In', 'Token Expiry'],\n style: {\n head: ['cyan'],\n border: ['gray']\n },\n colWidths: [30, 12, 28]\n })\n \n for (const email of emails) {\n const tokenManager = getTokenManagerForAccount(email)\n const isActive = email === activeEmail\n const nameDisplay = isActive ? `${email} [*]` : email\n \n if (tokenManager.isLoggedIn()) {\n const expiresAt = tokenManager.getExpiresAt()\n const isExpired = tokenManager.isTokenExpired()\n \n let expiryDisplay = '-'\n if (expiresAt) {\n expiryDisplay = expiresAt.toLocaleString()\n if (isExpired) {\n expiryDisplay = `⚠️ ${expiryDisplay}`\n }\n }\n \n table.push([\n nameDisplay,\n '✅',\n expiryDisplay\n ])\n } else {\n table.push([\n nameDisplay,\n '❌',\n 'Invalid or missing'\n ])\n }\n }\n \n console.log(table.toString())\n console.log()\n console.log('[*] = active account')\n console.log()\n}\n\nexport function statusCommand(options: StatusOptions = {}): void {\n if (options.all) {\n showAllAccountsStatus()\n return\n }\n \n if (options.account) {\n const manager = getAccountManager()\n if (!manager.hasAccount(options.account)) {\n warn(`Account '${options.account}' not found.`)\n return\n }\n showSingleAccountStatus(options.account)\n return\n }\n \n showSingleAccountStatus()\n}\n","/**\n * Google Cloud Code API client\n */\n\nimport { randomUUID } from 'crypto'\nimport { debug } from '../core/logger.js'\nimport { APIError, AuthenticationError, NetworkError, RateLimitError } from '../core/errors.js'\nimport type { TokenManager } from './token-manager.js'\n\n// Base URLs - try production first, then sandbox (matching example.ts)\nconst BASE_URLS = [\n 'https://cloudcode-pa.googleapis.com',\n 'https://daily-cloudcode-pa.sandbox.googleapis.com'\n]\nconst BASE_URL = BASE_URLS[0] // Default for non-trigger API calls\nconst USER_AGENT = 'antigravity'\n\n// Retry configuration (matching example.ts)\nconst MAX_TRIGGER_ATTEMPTS = 3\nconst STREAM_PATH = '/v1internal:streamGenerateContent?alt=sse'\n\n// System prompt - MUST match exact Cockpit extension format\nconst SYSTEM_PROMPT = 'You are Antigravity, a powerful agentic AI coding assistant designed by the Google Deepmind team working on Advanced Agentic Coding. You are pair programming with a USER to solve their coding task. The task may require creating a new codebase, modifying or debugging an existing codebase, or simply answering a question.**Absolute paths only****Proactiveness**'\n\n// Standard metadata for Cloud Code API calls\nconst METADATA = {\n ideType: 'ANTIGRAVITY',\n platform: 'PLATFORM_UNSPECIFIED',\n pluginType: 'GEMINI'\n}\n\n/**\n * Raw API response types (based on extension code patterns)\n */\nexport interface LoadCodeAssistResponse {\n codeAssistEnabled?: boolean\n planInfo?: {\n monthlyPromptCredits?: number\n planType?: string\n }\n availablePromptCredits?: number\n cloudaicompanionProject?: string | { id?: string }\n currentTier?: {\n id?: string\n name?: string\n description?: string\n }\n paidTier?: {\n id?: string\n }\n allowedTiers?: Array<{ id?: string; isDefault?: boolean }>\n}\n\n/**\n * Model info in the response - keyed by model ID\n */\nexport interface ModelInfo {\n displayName?: string\n model?: string\n label?: string\n quotaInfo?: {\n remainingFraction?: number\n resetTime?: string\n isExhausted?: boolean\n }\n maxTokens?: number\n recommended?: boolean\n supportsImages?: boolean\n supportsThinking?: boolean\n modelProvider?: string\n}\n\n/**\n * The actual response structure - models is an object, not an array\n */\nexport interface FetchAvailableModelsResponse {\n models?: Record<string, ModelInfo>\n defaultAgentModelId?: string\n}\n\n/**\n * Cloud Code API client\n */\nexport class CloudCodeClient {\n private projectId?: string\n \n constructor(private tokenManager: TokenManager) {\n // Initialize project ID from cached tokens (stored during login/quota fetch)\n this.projectId = tokenManager.getProjectId()\n }\n \n /**\n * Make an authenticated API request\n */\n private async request<T>(endpoint: string, body?: unknown): Promise<T> {\n const token = await this.tokenManager.getValidAccessToken()\n const url = `${BASE_URL}${endpoint}`\n \n debug('cloudcode', `Calling ${endpoint}`)\n \n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n 'User-Agent': USER_AGENT\n },\n body: body ? JSON.stringify(body) : undefined\n })\n \n debug('cloudcode', `Response status: ${response.status}`)\n \n if (response.status === 401 || response.status === 403) {\n const errorBody = await response.text()\n debug('cloudcode', `Auth error body: ${errorBody}`)\n throw new AuthenticationError('Authentication failed. Please run: antigravity-usage login')\n }\n \n if (response.status === 429) {\n const retryAfter = response.headers.get('retry-after')\n const retryMs = retryAfter ? parseInt(retryAfter) * 1000 : undefined\n throw new RateLimitError('Rate limited by Google API', retryMs)\n }\n \n if (response.status >= 500) {\n throw new APIError(`Server error: ${response.status}`, response.status)\n }\n \n if (!response.ok) {\n const errorText = await response.text()\n debug('cloudcode', 'API error response', errorText)\n throw new APIError(`API request failed: ${response.status}`, response.status)\n }\n \n const data = await response.json() as T\n debug('cloudcode', 'API call successful')\n return data\n } catch (err) {\n if (err instanceof AuthenticationError || \n err instanceof RateLimitError || \n err instanceof APIError) {\n throw err\n }\n \n if (err instanceof TypeError && err.message.includes('fetch')) {\n throw new NetworkError('Network error. Please check your connection.')\n }\n \n throw err\n }\n }\n \n /**\n * Load code assist status and plan info\n * Also extracts project ID for subsequent calls\n */\n async loadCodeAssist(): Promise<LoadCodeAssistResponse> {\n // Use complete metadata as per working implementation\n const response = await this.request<LoadCodeAssistResponse>('/v1internal:loadCodeAssist', {\n metadata: METADATA\n })\n \n // Store project ID for fetchAvailableModels\n // Handle both string and object formats\n if (response.cloudaicompanionProject) {\n if (typeof response.cloudaicompanionProject === 'string') {\n this.projectId = response.cloudaicompanionProject\n } else if (response.cloudaicompanionProject.id) {\n this.projectId = response.cloudaicompanionProject.id\n }\n debug('cloudcode', `Project ID: ${this.projectId}`)\n }\n \n return response\n }\n \n /**\n * Extract project ID from loadCodeAssist response\n */\n private extractProjectId(response: LoadCodeAssistResponse): void {\n // Try multiple possible field names\n const projectId = response.cloudaicompanionProject \n || (response as any).project \n || (response as any).projectId\n || (response as any).cloudProject\n \n if (projectId && typeof projectId === 'string' && projectId.length > 0) {\n this.projectId = projectId\n debug('cloudcode', `Project ID extracted: ${this.projectId}`)\n } else {\n debug('cloudcode', 'No project ID found in response')\n }\n }\n \n /**\n * Resolve project ID with onboarding retry if needed\n * This is the recommended way to get projectId reliably\n */\n async resolveProjectId(maxRetries: number = 5, retryDelayMs: number = 2000): Promise<string | undefined> {\n // If already have projectId, return it\n if (this.projectId) {\n debug('cloudcode', `Using cached project ID: ${this.projectId}`)\n return this.projectId\n }\n \n // Try loading first\n const loadResponse = await this.loadCodeAssist()\n if (this.projectId) {\n return this.projectId\n }\n \n // Project ID not found - may need onboarding\n debug('cloudcode', 'Project ID not found, attempting onboarding...')\n \n // Pick onboarding tier from allowedTiers\n const tiers = loadResponse.allowedTiers || []\n let tierId: string | undefined\n \n // Prefer default tier, then paidTier, then first available\n const defaultTier = tiers.find((t: any) => t.isDefault)\n if (defaultTier) {\n tierId = defaultTier.id\n } else if (loadResponse.paidTier?.id) {\n tierId = loadResponse.paidTier.id\n } else if ((loadResponse as any).currentTier?.id) {\n tierId = (loadResponse as any).currentTier.id\n } else if (tiers.length > 0) {\n tierId = tiers[0].id\n }\n \n if (!tierId) {\n debug('cloudcode', 'No tier available for onboarding')\n return undefined\n }\n \n debug('cloudcode', `Onboarding with tier: ${tierId}`)\n \n // Try onboarding (call to select/confirm tier)\n try {\n await this.request('/v1internal:onboardUser', {\n tierId,\n metadata: { \n ideType: 'ANTIGRAVITY',\n platform: 'PLATFORM_UNSPECIFIED',\n pluginType: 'GEMINI'\n }\n })\n } catch (err) {\n debug('cloudcode', 'Onboarding call failed (may be expected):', err)\n // Continue with retry loop anyway\n }\n \n // Retry loop to get project ID\n for (let i = 0; i < maxRetries; i++) {\n debug('cloudcode', `Retry ${i + 1}/${maxRetries} for project ID...`)\n \n // Wait before retry\n await new Promise(resolve => setTimeout(resolve, retryDelayMs))\n \n // Try loading again\n await this.loadCodeAssist()\n \n if (this.projectId) {\n debug('cloudcode', `Project ID resolved after ${i + 1} retries: ${this.projectId}`)\n return this.projectId\n }\n }\n \n debug('cloudcode', 'Failed to resolve project ID after all retries')\n return undefined\n }\n \n /**\n * Fetch available models with quota info\n * Requires project ID from loadCodeAssist\n */\n async fetchAvailableModels(): Promise<FetchAvailableModelsResponse> {\n const body = this.projectId ? { project: this.projectId } : {}\n return this.request<FetchAvailableModelsResponse>('/v1internal:fetchAvailableModels', body)\n }\n \n /**\n * Generate content using a specific model (Agent Request Format)\n * Used for wake-up triggers to warm up models\n * \n * Per docs/trigger.md, must use the agent request format with:\n * - project: Cloud Code project ID\n * - requestId: unique ID\n * - model: model ID\n * - userAgent: \"antigravity\"\n * - requestType: \"agent\"\n * - request: contains contents, session_id, systemInstruction, generationConfig\n * \n * @param modelId Model ID to use\n * @param prompt User prompt to send\n * @param maxOutputTokens Maximum tokens to generate (0 = no limit)\n * @returns Generated text and optional token usage\n */\n async generateContent(\n modelId: string, \n prompt: string, \n maxOutputTokens?: number\n ): Promise<{ text: string; tokensUsed?: { prompt: number; completion: number; total: number } }> {\n debug('cloudcode', `Generating content with model: ${modelId}`)\n debug('cloudcode', `Current projectId: ${this.projectId}`)\n \n // CRITICAL: Always warm up session with loadCodeAssist before trigger request\n // This is required for the API to accept our requests (matching example.ts)\n debug('cloudcode', 'Warming up session with loadCodeAssist...')\n try {\n await this.loadCodeAssist()\n debug('cloudcode', `Session warmed up, projectId: ${this.projectId}`)\n } catch (err) {\n debug('cloudcode', 'Warmup failed (continuing anyway):', err)\n }\n \n // Generate unique IDs\n const requestId = randomUUID()\n const sessionId = randomUUID()\n \n // System instruction - MUST match exact Cockpit extension format\n const systemInstruction = {\n parts: [{ text: SYSTEM_PROMPT }]\n }\n \n // Generation config\n const generationConfig: Record<string, unknown> = {\n temperature: 0\n }\n if (maxOutputTokens && maxOutputTokens > 0) {\n generationConfig.maxOutputTokens = maxOutputTokens\n }\n \n // Build agent request body per docs/trigger.md\n // Project may be optional if the API can infer it from the token\n const body: Record<string, unknown> = {\n requestId,\n model: modelId,\n userAgent: 'antigravity',\n requestType: 'agent',\n request: {\n contents: [{\n role: 'user',\n parts: [{ text: prompt }]\n }],\n session_id: sessionId,\n systemInstruction,\n generationConfig\n }\n }\n \n // Add project only if we have one\n if (this.projectId) {\n body.project = this.projectId\n debug('cloudcode', `Using project ID: ${this.projectId}`)\n } else {\n debug('cloudcode', 'Sending request WITHOUT project ID')\n }\n \n debug('cloudcode', `Request body:`, JSON.stringify(body, null, 2))\n \n // Get fresh access token\n const token = await this.tokenManager.getValidAccessToken()\n \n // Helper: Calculate backoff delay (matching example.ts)\n const getBackoffDelay = (attempt: number): number => {\n const raw = 500 * Math.pow(2, attempt - 2)\n const jitter = Math.random() * 100\n return Math.min(raw + jitter, 4000)\n }\n \n // Helper: Sleep function\n const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))\n \n // Helper: Parse SSE response\n const parseSSEResponse = (sseText: string): { text: string; tokensUsed?: { prompt: number; completion: number; total: number } } => {\n let fullText = ''\n let tokensUsed: { prompt: number; completion: number; total: number } | undefined\n \n for (const line of sseText.split('\\n')) {\n if (line.startsWith('data: ')) {\n const jsonStr = line.substring(6)\n if (jsonStr.trim() === '[DONE]') continue\n \n try {\n const data = JSON.parse(jsonStr)\n // Handle both response formats: with and without 'response' wrapper\n const responseData = data.response || data\n const candidateText = responseData.candidates?.[0]?.content?.parts?.[0]?.text\n if (candidateText) {\n fullText += candidateText\n }\n if (responseData.usageMetadata) {\n tokensUsed = {\n prompt: responseData.usageMetadata.promptTokenCount || 0,\n completion: responseData.usageMetadata.candidatesTokenCount || 0,\n total: responseData.usageMetadata.totalTokenCount || 0\n }\n }\n } catch {\n // Ignore parse errors\n }\n }\n }\n \n return { text: fullText, tokensUsed }\n }\n \n // CRITICAL: Try each base URL with retries (matching example.ts EXACTLY)\n for (const baseUrl of BASE_URLS) {\n for (let attempt = 1; attempt <= MAX_TRIGGER_ATTEMPTS; attempt++) {\n // Backoff BEFORE request (except first attempt) - matching example.ts\n if (attempt > 1) {\n const delay = getBackoffDelay(attempt)\n debug('cloudcode', `Retry ${attempt}/${MAX_TRIGGER_ATTEMPTS} in ${Math.round(delay)}ms...`)\n await sleep(delay)\n }\n \n const url = `${baseUrl}${STREAM_PATH}`\n debug('cloudcode', `Attempt ${attempt}/${MAX_TRIGGER_ATTEMPTS} on ${baseUrl}`)\n \n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'User-Agent': USER_AGENT,\n 'Content-Type': 'application/json',\n 'Accept-Encoding': 'gzip' // CRITICAL: Must match example.ts\n },\n body: JSON.stringify(body)\n })\n \n const text = await response.text()\n debug('cloudcode', `Response ${response.status}`)\n debug('cloudcode', `Response text: ${text.slice(0, 500)}`)\n \n // Handle retryable errors (429 or 5xx) - matching example.ts\n if (response.status === 429 || response.status >= 500) {\n debug('cloudcode', `${response.status} - retryable`)\n if (attempt === MAX_TRIGGER_ATTEMPTS) {\n debug('cloudcode', 'Max attempts on this URL, trying next...')\n break // Try next base URL\n }\n continue // Retry on same URL\n }\n \n // Success!\n if (response.ok) {\n debug('cloudcode', 'Request succeeded!')\n const parsed = parseSSEResponse(text)\n debug('cloudcode', `Generated ${parsed.text.length} chars, tokens: ${parsed.tokensUsed?.total || 'unknown'}`)\n return parsed\n }\n \n // Non-retryable error (4xx except 429)\n debug('cloudcode', `Non-retryable error: ${response.status}`)\n throw new Error(`API request failed: ${response.status} - ${text}`)\n \n } catch (err) {\n // Network or other error\n if (err instanceof Error && !err.message.startsWith('API request failed')) {\n debug('cloudcode', `Network error: ${err.message}`)\n if (attempt === MAX_TRIGGER_ATTEMPTS) {\n debug('cloudcode', 'Max attempts on this URL, trying next...')\n break // Try next base URL\n }\n continue // Retry on same URL\n }\n throw err // Re-throw API errors\n }\n }\n }\n \n // All URLs and retries exhausted\n throw new Error('All trigger attempts failed across all base URLs')\n }\n}\n","/**\n * Parser for Cloud Code API responses\n */\n\nimport { debug } from '../core/logger.js'\nimport type { QuotaSnapshot, ModelQuotaInfo, PromptCreditsInfo } from '../quota/types.js'\nimport type { LoadCodeAssistResponse, FetchAvailableModelsResponse, ModelInfo } from './cloudcode.js'\n\n/**\n * Parse reset time string to milliseconds until reset\n */\nfunction parseResetTime(resetTime?: string): number | undefined {\n if (!resetTime) return undefined\n\n try {\n const resetDate = new Date(resetTime)\n const now = Date.now()\n const diff = resetDate.getTime() - now\n return diff > 0 ? diff : undefined\n } catch {\n return undefined\n }\n}\n\n/**\n * Parse model info into ModelQuotaInfo\n */\nfunction parseModelInfo(modelId: string, model: ModelInfo): ModelQuotaInfo {\n const quotaInfo = model.quotaInfo\n\n return {\n label: model.displayName || model.label || modelId,\n modelId: modelId,\n remainingPercentage: quotaInfo?.remainingFraction,\n isExhausted: quotaInfo?.isExhausted ?? (quotaInfo?.remainingFraction === 0),\n resetTime: quotaInfo?.resetTime,\n timeUntilResetMs: parseResetTime(quotaInfo?.resetTime),\n isAutocompleteOnly: modelId.includes('gemini-2.5') || (model.displayName || '').includes('Gemini 2.5')\n }\n}\n\n/**\n * Parse prompt credits from loadCodeAssist response\n */\nfunction parsePromptCredits(response: LoadCodeAssistResponse): PromptCreditsInfo | undefined {\n const monthly = response.planInfo?.monthlyPromptCredits\n const available = response.availablePromptCredits\n\n if (monthly === undefined || available === undefined) {\n return undefined\n }\n\n const used = monthly - available\n const usedPercentage = monthly > 0 ? used / monthly : 0\n const remainingPercentage = monthly > 0 ? available / monthly : 0\n\n return {\n available,\n monthly,\n usedPercentage,\n remainingPercentage\n }\n}\n\n/**\n * Check if a model should be shown in quota display\n * Filter out internal models and only show recommended ones\n */\nfunction shouldShowModel(modelId: string, model: ModelInfo): boolean {\n // Skip internal models\n if (modelId.startsWith('chat_') || modelId.startsWith('tab_')) {\n return false\n }\n // Skip image generation models\n if (modelId.includes('image')) {\n return false\n }\n // Skip internal/experimental models\n if (modelId.startsWith('rev')) {\n return false\n }\n // Skip lite models that are just for specific features\n if (modelId.includes('mquery') || modelId.includes('lite')) {\n return false\n }\n // Only show models with quota info\n if (!model.quotaInfo) {\n return false\n }\n return true\n}\n\n/**\n * Parse API responses into a QuotaSnapshot\n */\nexport function parseQuotaSnapshot(\n codeAssistResponse: LoadCodeAssistResponse,\n modelsResponse: FetchAvailableModelsResponse,\n email?: string\n): QuotaSnapshot {\n debug('parser', 'Parsing quota snapshot')\n\n const promptCredits = parsePromptCredits(codeAssistResponse)\n const planType = codeAssistResponse.planInfo?.planType\n\n // Models is now an object keyed by model ID\n const modelsMap = modelsResponse.models || {}\n const models: ModelQuotaInfo[] = []\n\n for (const [modelId, modelInfo] of Object.entries(modelsMap)) {\n if (shouldShowModel(modelId, modelInfo)) {\n models.push(parseModelInfo(modelId, modelInfo))\n }\n }\n\n // Sort by displayName\n models.sort((a, b) => a.label.localeCompare(b.label))\n\n debug('parser', `Parsed ${models.length} models`)\n\n return {\n timestamp: new Date().toISOString(),\n method: 'google',\n email,\n planType,\n promptCredits,\n models\n }\n}\n","/**\n * Process detector - finds running Antigravity language server processes\n */\n\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\nimport { debug } from '../core/logger.js'\n\nconst execAsync = promisify(exec)\n\nexport interface AntigravityProcessInfo {\n pid: number\n csrfToken?: string\n extensionServerPort?: number\n commandLine: string\n}\n\n/**\n * Detects running Antigravity language server processes\n * Returns process info including PID and extracted command-line arguments\n */\nexport async function detectAntigravityProcess(): Promise<AntigravityProcessInfo | null> {\n const platform = process.platform\n \n debug('process-detector', `Detecting Antigravity process on platform: ${platform}`)\n \n if (platform === 'win32') {\n return detectOnWindows()\n } else {\n // macOS and Linux use similar commands\n return detectOnUnix()\n }\n}\n\n/**\n * Detect Antigravity process on Unix-like systems (macOS, Linux)\n */\nasync function detectOnUnix(): Promise<AntigravityProcessInfo | null> {\n try {\n // Use ps to list all processes with full command line\n // Look for processes containing 'antigravity' in their command\n const { stdout } = await execAsync('ps aux')\n \n const lines = stdout.split('\\n')\n \n for (const line of lines) {\n const lower = line.toLowerCase()\n if (!lower.includes('antigravity')) {\n continue\n }\n\n // Ignore remote server install scripts that contain broad \"server\" terms\n // but are not the language server process.\n if (lower.includes('server installation script')) {\n continue\n }\n\n const hasServerSignal =\n line.includes('language-server') ||\n line.includes('lsp') ||\n line.includes('--csrf_token') ||\n line.includes('--extension_server_port') ||\n line.includes('exa.language_server_pb')\n\n if (!hasServerSignal) {\n continue\n }\n\n debug('process-detector', `Found potential Antigravity process: ${line}`)\n\n const processInfo = parseUnixProcessLine(line)\n if (processInfo) {\n return processInfo\n }\n }\n \n debug('process-detector', 'No Antigravity process found')\n return null\n } catch (err) {\n debug('process-detector', 'Error detecting process on Unix', err)\n return null\n }\n}\n\n/**\n * Parse a Unix ps output line to extract process info\n */\nfunction parseUnixProcessLine(line: string): AntigravityProcessInfo | null {\n // ps aux format: USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND...\n const parts = line.trim().split(/\\s+/)\n \n if (parts.length < 11) {\n return null\n }\n \n const pid = parseInt(parts[1], 10)\n if (isNaN(pid)) {\n return null\n }\n \n // Command is everything from index 10 onwards\n const commandLine = parts.slice(10).join(' ')\n \n // Extract arguments from command line\n const csrfToken = extractArgument(commandLine, '--csrf_token')\n const extensionServerPort = extractArgument(commandLine, '--extension_server_port')\n \n return {\n pid,\n csrfToken: csrfToken || undefined,\n extensionServerPort: extensionServerPort ? parseInt(extensionServerPort, 10) : undefined,\n commandLine\n }\n}\n\n/**\n * Detect Antigravity process on Windows\n */\nasync function detectOnWindows(): Promise<AntigravityProcessInfo | null> {\n try {\n // Use WMIC to get process details with command line\n const { stdout } = await execAsync(\n 'wmic process where \"name like \\'%antigravity%\\' or commandline like \\'%antigravity%\\'\" get processid,commandline /format:csv',\n { maxBuffer: 10 * 1024 * 1024 } // 10MB buffer for long command lines\n )\n \n const lines = stdout.split('\\n').filter(line => line.trim() && !line.includes('Node,CommandLine,ProcessId'))\n const candidates: AntigravityProcessInfo[] = []\n\n for (const line of lines) {\n // CSV format: Node,CommandLine,ProcessId\n const parts = line.split(',')\n if (parts.length >= 3) {\n const commandLine = parts.slice(1, -1).join(',') // Command line might contain commas\n const pid = parseInt(parts[parts.length - 1].trim(), 10)\n \n if (!isNaN(pid) && commandLine.toLowerCase().includes('antigravity')) {\n candidates.push({\n pid,\n csrfToken: extractArgument(commandLine, '--csrf_token') || undefined,\n extensionServerPort: parsePortValue(extractArgument(commandLine, '--extension_server_port')),\n commandLine\n })\n }\n }\n }\n\n const selected = selectBestWindowsCandidate(candidates)\n if (selected) {\n debug('process-detector', `Selected Antigravity process on Windows: PID ${selected.pid}`)\n return selected\n }\n \n // Fallback: try PowerShell if WMIC doesn't work\n return await detectOnWindowsPowerShell()\n } catch (err) {\n debug('process-detector', 'Error detecting process on Windows with WMIC, trying PowerShell', err)\n return await detectOnWindowsPowerShell()\n }\n}\n\n/**\n * Fallback Windows detection using PowerShell\n */\nasync function detectOnWindowsPowerShell(): Promise<AntigravityProcessInfo | null> {\n try {\n const { stdout } = await execAsync(\n 'powershell -Command \"Get-Process | Where-Object { $_.ProcessName -like \\'*antigravity*\\' } | Select-Object Id, ProcessName | ConvertTo-Json\"'\n )\n \n if (!stdout.trim()) {\n return null\n }\n \n const processes = JSON.parse(stdout)\n const processList = Array.isArray(processes) ? processes : [processes]\n \n const candidates: AntigravityProcessInfo[] = []\n\n for (const proc of processList) {\n if (proc.Id) {\n // Get command line for this process\n const { stdout: cmdLine } = await execAsync(\n `powershell -Command \"(Get-CimInstance Win32_Process -Filter 'ProcessId = ${proc.Id}').CommandLine\"`\n )\n \n const commandLine = cmdLine.trim()\n if (!commandLine.toLowerCase().includes('antigravity')) {\n continue\n }\n\n candidates.push({\n pid: proc.Id,\n csrfToken: extractArgument(commandLine, '--csrf_token') || undefined,\n extensionServerPort: parsePortValue(extractArgument(commandLine, '--extension_server_port')),\n commandLine\n })\n }\n }\n\n const selected = selectBestWindowsCandidate(candidates)\n if (selected) {\n debug('process-detector', `Selected Antigravity process on Windows (PowerShell): PID ${selected.pid}`)\n return selected\n }\n\n return null\n } catch (err) {\n debug('process-detector', 'Error detecting process on Windows with PowerShell', err)\n return null\n }\n}\n\nfunction parsePortValue(rawPort: string | null): number | undefined {\n if (!rawPort) {\n return undefined\n }\n const parsed = parseInt(rawPort, 10)\n return isNaN(parsed) ? undefined : parsed\n}\n\nfunction scoreWindowsCandidate(candidate: AntigravityProcessInfo): number {\n const lower = candidate.commandLine.toLowerCase()\n\n let score = 0\n if (lower.includes('antigravity')) score += 1\n if (lower.includes('lsp')) score += 5\n if (candidate.extensionServerPort) score += 10\n if (candidate.csrfToken) score += 20\n if (\n lower.includes('language_server') ||\n lower.includes('language-server') ||\n lower.includes('exa.language_server_pb')\n ) {\n score += 50\n }\n\n return score\n}\n\nfunction selectBestWindowsCandidate(candidates: AntigravityProcessInfo[]): AntigravityProcessInfo | null {\n if (candidates.length === 0) {\n return null\n }\n\n debug('process-detector', `Found ${candidates.length} Antigravity candidate process(es) on Windows`)\n\n let best: AntigravityProcessInfo | null = null\n let bestScore = -1\n for (const candidate of candidates) {\n const score = scoreWindowsCandidate(candidate)\n if (score > bestScore) {\n best = candidate\n bestScore = score\n }\n }\n\n if (best) {\n debug('process-detector', `Selected PID ${best.pid} with score ${bestScore}`)\n }\n\n return best\n}\n\n/**\n * Extract argument value from command line\n * Supports formats: --arg=value and --arg value\n */\nfunction extractArgument(commandLine: string, argName: string): string | null {\n // Try --arg=value format\n const eqRegex = new RegExp(`${argName}=([^\\\\s\"']+|\"[^\"]*\"|'[^']*')`, 'i')\n const eqMatch = commandLine.match(eqRegex)\n if (eqMatch) {\n return eqMatch[1].replace(/^[\"']|[\"']$/g, '') // Remove quotes\n }\n \n // Try --arg value format\n const spaceRegex = new RegExp(`${argName}\\\\s+([^\\\\s\"']+|\"[^\"]*\"|'[^']*')`, 'i')\n const spaceMatch = commandLine.match(spaceRegex)\n if (spaceMatch) {\n return spaceMatch[1].replace(/^[\"']|[\"']$/g, '') // Remove quotes\n }\n \n return null\n}\n","/**\n * Port detective - discovers listening ports for a given process\n */\n\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\nimport { debug } from '../core/logger.js'\n\nconst execAsync = promisify(exec)\n\n/**\n * Discovers which ports a process is listening on\n * @param pid Process ID to check\n * @returns Array of port numbers the process is listening on\n */\nexport async function discoverPorts(pid: number): Promise<number[]> {\n const platform = process.platform\n \n debug('port-detective', `Discovering ports for PID ${pid} on platform: ${platform}`)\n \n if (platform === 'win32') {\n return discoverPortsOnWindows(pid)\n } else if (platform === 'darwin') {\n return discoverPortsOnMacOS(pid)\n } else {\n return discoverPortsOnLinux(pid)\n }\n}\n\n/**\n * Discover listening ports on macOS using lsof\n */\nasync function discoverPortsOnMacOS(pid: number): Promise<number[]> {\n try {\n // lsof -nP -iTCP -sTCP:LISTEN -a -p <PID>\n const { stdout } = await execAsync(`lsof -nP -iTCP -sTCP:LISTEN -a -p ${pid}`)\n \n const ports: number[] = []\n const lines = stdout.split('\\n')\n \n for (const line of lines) {\n // Format: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\n // NAME column contains: *:PORT or IP:PORT (LISTEN)\n const match = line.match(/:(\\d+)\\s+\\(LISTEN\\)/)\n if (match) {\n const port = parseInt(match[1], 10)\n if (!isNaN(port) && !ports.includes(port)) {\n ports.push(port)\n }\n }\n }\n \n debug('port-detective', `Found ports on macOS: ${ports.join(', ')}`)\n return ports\n } catch (err) {\n debug('port-detective', 'Error discovering ports on macOS', err)\n return []\n }\n}\n\n/**\n * Discover listening ports on Linux using ss or netstat\n */\nasync function discoverPortsOnLinux(pid: number): Promise<number[]> {\n try {\n // Try ss first (modern)\n const { stdout } = await execAsync(`ss -tlnp | grep \"pid=${pid},\"`)\n \n const ports: number[] = []\n const lines = stdout.split('\\n')\n \n for (const line of lines) {\n // Format: State Recv-Q Send-Q Local Address:Port Peer Address:Port Process\n const match = line.match(/:(\\d+)\\s/)\n if (match) {\n const port = parseInt(match[1], 10)\n if (!isNaN(port) && !ports.includes(port)) {\n ports.push(port)\n }\n }\n }\n \n if (ports.length > 0) {\n debug('port-detective', `Found ports on Linux (ss): ${ports.join(', ')}`)\n return ports\n }\n \n // Fallback to netstat\n return await discoverPortsOnLinuxNetstat(pid)\n } catch {\n // ss might not find anything, try netstat\n return await discoverPortsOnLinuxNetstat(pid)\n }\n}\n\n/**\n * Fallback Linux port discovery using netstat\n */\nasync function discoverPortsOnLinuxNetstat(pid: number): Promise<number[]> {\n try {\n const { stdout } = await execAsync(`netstat -tlnp 2>/dev/null | grep \"${pid}/\"`)\n \n const ports: number[] = []\n const lines = stdout.split('\\n')\n \n for (const line of lines) {\n // Format: Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program\n const match = line.match(/:(\\d+)\\s/)\n if (match) {\n const port = parseInt(match[1], 10)\n if (!isNaN(port) && !ports.includes(port)) {\n ports.push(port)\n }\n }\n }\n \n debug('port-detective', `Found ports on Linux (netstat): ${ports.join(', ')}`)\n return ports\n } catch (err) {\n debug('port-detective', 'Error discovering ports on Linux', err)\n return []\n }\n}\n\n/**\n * Discover listening ports on Windows using netstat\n */\nasync function discoverPortsOnWindows(pid: number): Promise<number[]> {\n try {\n // netstat -ano shows all connections with PIDs\n const { stdout } = await execAsync('netstat -ano')\n \n const ports: number[] = []\n const lines = stdout.split('\\n')\n \n for (const line of lines) {\n // Format: Proto Local Address Foreign Address State PID\n // Look for LISTENING state and matching PID\n if (line.includes('LISTENING')) {\n const parts = line.trim().split(/\\s+/)\n const linePid = parseInt(parts[parts.length - 1], 10)\n \n if (linePid === pid) {\n // Extract port from local address (format: IP:PORT or [::]:PORT)\n const localAddr = parts[1]\n const portMatch = localAddr.match(/:(\\d+)$/)\n if (portMatch) {\n const port = parseInt(portMatch[1], 10)\n if (!isNaN(port) && !ports.includes(port)) {\n ports.push(port)\n }\n }\n }\n }\n }\n \n debug('port-detective', `Found ports on Windows: ${ports.join(', ')}`)\n return ports\n } catch (err) {\n debug('port-detective', 'Error discovering ports on Windows', err)\n return []\n }\n}\n","/**\n * Port prober - probes ports to find the Connect API endpoint\n */\n\nimport https from 'https'\nimport http from 'http'\nimport { debug } from '../core/logger.js'\n\nconst CONNECT_RPC_PATH = '/exa.language_server_pb.LanguageServerService/GetUnleashData'\nconst VALID_CONNECT_STATUSES = new Set([200, 401])\n\nexport interface ProbeResult {\n baseUrl: string\n protocol: 'https' | 'http'\n port: number\n}\n\n/**\n * Probes ports to find a working Connect API endpoint\n * Tries HTTPS first (with self-signed cert handling), then HTTP\n * @param ports Array of port numbers to probe\n * @param csrfToken Optional CSRF token for authentication\n * @param timeout Timeout per probe in ms (default 500ms)\n * @returns ProbeResult with working endpoint, or null if none found\n */\nexport async function probeForConnectAPI(ports: number[], csrfToken?: string, timeout = 500): Promise<ProbeResult | null> {\n debug('port-prober', `Probing ${ports.length} ports: ${ports.join(', ')}`)\n \n // Probe all ports concurrently\n const probePromises = ports.map(port => probePort(port, csrfToken, timeout))\n const results = await Promise.allSettled(probePromises)\n \n // Find first successful probe\n for (let i = 0; i < results.length; i++) {\n const result = results[i]\n if (result.status === 'fulfilled' && result.value) {\n debug('port-prober', `Found working endpoint: ${result.value.baseUrl}`)\n return result.value\n }\n }\n \n debug('port-prober', 'No working Connect API endpoint found')\n return null\n}\n\n/**\n * Probe a single port for Connect API\n * Tries HTTPS first, then HTTP\n */\nasync function probePort(port: number, csrfToken?: string, timeout = 500): Promise<ProbeResult | null> {\n // Try HTTPS first (language server typically uses self-signed certs)\n const httpsResult = await probeHttps(port, timeout, csrfToken)\n if (httpsResult) {\n return httpsResult\n }\n \n // Fallback to HTTP\n const httpResult = await probeHttp(port, timeout, csrfToken)\n if (httpResult) {\n return httpResult\n }\n \n return null\n}\n\n/**\n * Probe a port with HTTPS (allowing self-signed certificates)\n * Uses Connect RPC GetUnleashData endpoint to verify it's the correct port\n */\nfunction probeHttps(port: number, timeout: number, csrfToken?: string): Promise<ProbeResult | null> {\n return new Promise((resolve) => {\n const options: https.RequestOptions = {\n hostname: '127.0.0.1',\n port,\n path: CONNECT_RPC_PATH,\n method: 'POST',\n timeout,\n rejectUnauthorized: false, // Allow self-signed certificates\n headers: {\n 'Content-Type': 'application/json',\n 'Connect-Protocol-Version': '1',\n ...(csrfToken ? { 'X-Codeium-Csrf-Token': csrfToken } : {})\n }\n }\n \n const req = https.request(options, (res) => {\n if (res.statusCode && VALID_CONNECT_STATUSES.has(res.statusCode)) {\n debug('port-prober', `HTTPS Connect RPC probe on port ${port}: status ${res.statusCode} - valid connect port`)\n resolve({\n baseUrl: `https://127.0.0.1:${port}`,\n protocol: 'https',\n port\n })\n } else {\n debug('port-prober', `HTTPS probe on port ${port}: status ${res.statusCode} - not connect port`)\n resolve(null)\n }\n \n // Consume response data to free up memory\n res.resume()\n })\n \n req.on('error', (err) => {\n debug('port-prober', `HTTPS probe on port ${port} failed: ${err.message}`)\n resolve(null)\n })\n \n req.on('timeout', () => {\n debug('port-prober', `HTTPS probe on port ${port} timed out`)\n req.destroy()\n resolve(null)\n })\n \n // Send the Connect RPC request body\n req.write(JSON.stringify({ wrapper_data: {} }))\n req.end()\n })\n}\n\n/**\n * Probe a port with HTTP\n */\nfunction probeHttp(port: number, timeout: number, csrfToken?: string): Promise<ProbeResult | null> {\n return new Promise((resolve) => {\n const options: http.RequestOptions = {\n hostname: '127.0.0.1',\n port,\n path: CONNECT_RPC_PATH,\n method: 'POST',\n timeout,\n headers: {\n 'Content-Type': 'application/json',\n 'Connect-Protocol-Version': '1',\n ...(csrfToken ? { 'X-Codeium-Csrf-Token': csrfToken } : {})\n }\n }\n \n const req = http.request(options, (res) => {\n let data = ''\n res.on('data', (chunk) => {\n data += chunk.toString()\n })\n\n res.on('end', () => {\n if (\n data.toLowerCase().includes('client sent an http request to an https server')\n ) {\n debug('port-prober', `HTTP probe on port ${port}: protocol mismatch response, rejecting`)\n resolve(null)\n return\n }\n\n if (res.statusCode && VALID_CONNECT_STATUSES.has(res.statusCode)) {\n debug('port-prober', `HTTP Connect RPC probe on port ${port}: status ${res.statusCode} - valid connect port`)\n resolve({\n baseUrl: `http://127.0.0.1:${port}`,\n protocol: 'http',\n port\n })\n return\n }\n\n debug('port-prober', `HTTP probe on port ${port}: status ${res.statusCode} - not connect port`)\n resolve(null)\n })\n })\n \n req.on('error', (err) => {\n debug('port-prober', `HTTP probe on port ${port} failed: ${err.message}`)\n resolve(null)\n })\n \n req.on('timeout', () => {\n debug('port-prober', `HTTP probe on port ${port} timed out`)\n req.destroy()\n resolve(null)\n })\n \n req.write(JSON.stringify({ wrapper_data: {} }))\n req.end()\n })\n}\n","/**\n * Connect client - client for Antigravity Connect API\n */\n\nimport https from 'https'\nimport http from 'http'\nimport { debug } from '../core/logger.js'\n\nexport interface ConnectUserStatus {\n // Basic status fields\n isAuthenticated?: boolean\n email?: string\n \n // Quota information (structure may vary based on actual API)\n quota?: {\n promptCredits?: {\n used?: number\n limit?: number\n remaining?: number\n }\n models?: Array<{\n modelId: string\n displayName?: string\n label?: string\n quota?: {\n remaining?: number\n limit?: number\n usedPercentage?: number\n remainingPercentage?: number\n resetTime?: string\n timeUntilResetMs?: number\n }\n isExhausted?: boolean\n }>\n }\n \n // Raw response for debugging\n raw?: unknown\n}\n\nexport interface ConnectModelInfo {\n modelId: string\n displayName?: string\n label?: string\n quota?: {\n remaining?: number\n limit?: number\n usedPercentage?: number\n remainingPercentage?: number\n resetTime?: string\n timeUntilResetMs?: number\n }\n isExhausted?: boolean\n}\n\nexport class ConnectClient {\n private baseUrl: string\n private csrfToken: string | undefined\n private isHttps: boolean\n \n constructor(baseUrl: string, csrfToken?: string) {\n this.baseUrl = baseUrl\n this.csrfToken = csrfToken\n this.isHttps = baseUrl.startsWith('https://')\n \n debug('connect-client', `Initialized with baseUrl: ${baseUrl}, hasToken: ${!!csrfToken}`)\n }\n \n /**\n * Get user status including quota information\n * Uses Connect RPC protocol to communicate with Antigravity language server\n */\n async getUserStatus(): Promise<ConnectUserStatus> {\n debug('connect-client', 'Fetching user status via Connect RPC')\n \n // Use the correct Connect RPC endpoint\n const endpoint = '/exa.language_server_pb.LanguageServerService/GetUserStatus'\n \n try {\n const response = await this.request('POST', endpoint, {\n metadata: {\n ideName: 'antigravity',\n extensionName: 'antigravity',\n locale: 'en'\n }\n })\n \n if (response) {\n debug('connect-client', `Got response from ${endpoint}`)\n return this.parseUserStatus(response)\n }\n } catch (err) {\n debug('connect-client', `Connect RPC call failed: ${err}`)\n throw new Error(`Failed to fetch user status: ${err instanceof Error ? err.message : 'Unknown error'}`)\n }\n \n throw new Error('Could not fetch user status from Connect RPC endpoint')\n }\n \n /**\n * Make an HTTP(S) request to the Connect API\n */\n private request(method: string, path: string, body?: unknown): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const url = new URL(path, this.baseUrl)\n \n const headers: Record<string, string> = {\n 'Accept': 'application/json',\n 'Content-Type': 'application/json',\n 'Connect-Protocol-Version': '1',\n }\n \n if (this.csrfToken) {\n // Use the correct CSRF header name for Antigravity Connect RPC\n headers['X-Codeium-Csrf-Token'] = this.csrfToken\n }\n \n const options = {\n hostname: url.hostname,\n port: url.port,\n path: url.pathname,\n method,\n headers,\n timeout: 5000,\n rejectUnauthorized: false, // Allow self-signed certificates\n }\n \n const protocol = this.isHttps ? https : http\n \n const req = protocol.request(options, (res) => {\n let data = ''\n \n res.on('data', (chunk) => {\n data += chunk\n })\n \n res.on('end', () => {\n if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {\n try {\n const parsed = JSON.parse(data)\n resolve(parsed)\n } catch {\n resolve(data)\n }\n } else if (res.statusCode === 404) {\n // Endpoint not found, try next\n reject(new Error(`Endpoint not found: ${path}`))\n } else {\n reject(new Error(`HTTP ${res.statusCode}: ${data}`))\n }\n })\n })\n \n req.on('error', (err) => {\n reject(err)\n })\n \n req.on('timeout', () => {\n req.destroy()\n reject(new Error('Request timed out'))\n })\n \n if (body) {\n req.write(JSON.stringify(body))\n }\n \n req.end()\n })\n }\n \n /**\n * Parse raw API response into ConnectUserStatus\n */\n private parseUserStatus(response: unknown): ConnectUserStatus {\n debug('connect-client', 'Raw response:', JSON.stringify(response, null, 2))\n \n const status: ConnectUserStatus = {\n raw: response\n }\n \n if (typeof response !== 'object' || response === null) {\n return status\n }\n \n const data = response as Record<string, unknown>\n \n // The actual response is nested under 'userStatus'\n const userStatus = (data.userStatus as Record<string, unknown>) || data\n \n // Extract email from userStatus\n if ('email' in userStatus && typeof userStatus.email === 'string') {\n status.email = userStatus.email\n }\n \n // Extract authentication status\n if ('isAuthenticated' in userStatus) {\n status.isAuthenticated = Boolean(userStatus.isAuthenticated)\n }\n \n // Extract quota from the nested structure\n status.quota = this.extractQuota(userStatus)\n \n return status\n }\n \n /**\n * Extract quota information from response\n */\n private extractQuota(data: Record<string, unknown>): ConnectUserStatus['quota'] {\n const quota: ConnectUserStatus['quota'] = {}\n \n // Extract prompt credits from planStatus structure\n const planStatus = data.planStatus as Record<string, unknown> | undefined\n if (planStatus) {\n const available = planStatus.availablePromptCredits\n const planInfo = planStatus.planInfo as Record<string, unknown> | undefined\n const monthly = planInfo?.monthlyPromptCredits\n \n if (typeof available === 'number' && typeof monthly === 'number') {\n const used = monthly - available\n quota.promptCredits = {\n used,\n limit: monthly,\n remaining: available\n }\n }\n }\n \n // Extract models from cascadeModelConfigData\n const cascadeData = data.cascadeModelConfigData as Record<string, unknown> | undefined\n const clientModelConfigs = cascadeData?.clientModelConfigs\n \n if (Array.isArray(clientModelConfigs)) {\n quota.models = clientModelConfigs.map(this.parseModel.bind(this))\n }\n \n return quota\n }\n \n /**\n * Parse a single model from the response\n */\n private parseModel(model: unknown): ConnectModelInfo {\n if (typeof model !== 'object' || model === null) {\n return {\n modelId: 'unknown',\n isExhausted: false\n }\n }\n \n const m = model as Record<string, unknown>\n \n // Extract model ID from modelOrAlias structure\n const modelOrAlias = m.modelOrAlias as Record<string, unknown> | undefined\n const modelId = typeof modelOrAlias?.model === 'string' ? modelOrAlias.model : 'unknown'\n \n // Extract quota info\n const quotaInfo = m.quotaInfo as Record<string, unknown> | undefined\n const remainingFraction = typeof quotaInfo?.remainingFraction === 'number' ? quotaInfo.remainingFraction : undefined\n const resetTime = typeof quotaInfo?.resetTime === 'string' ? quotaInfo.resetTime : undefined\n \n return {\n modelId,\n displayName: typeof m.label === 'string' ? m.label : undefined,\n label: typeof m.label === 'string' ? m.label : undefined,\n quota: {\n remaining: undefined,\n limit: undefined,\n usedPercentage: remainingFraction !== undefined ? (1 - remainingFraction) : undefined,\n remainingPercentage: remainingFraction,\n resetTime,\n timeUntilResetMs: resetTime ? this.parseResetTime(resetTime) : undefined,\n },\n isExhausted: remainingFraction === 0\n }\n }\n \n /**\n * Parse reset time to milliseconds until reset\n */\n private parseResetTime(resetTime: string): number | undefined {\n try {\n const resetDate = new Date(resetTime)\n const now = Date.now()\n const diff = resetDate.getTime() - now\n return diff > 0 ? diff : undefined\n } catch {\n return undefined\n }\n }\n}\n","/**\n * Local parser - converts Connect API response to QuotaSnapshot format\n */\n\nimport type { QuotaSnapshot, ModelQuotaInfo, PromptCreditsInfo } from '../quota/types.js'\nimport type { ConnectUserStatus } from './connect-client.js'\nimport { debug } from '../core/logger.js'\n\n/**\n * Parse Connect API user status into QuotaSnapshot format\n */\nexport function parseLocalQuotaSnapshot(userStatus: ConnectUserStatus): QuotaSnapshot {\n debug('local-parser', 'Parsing local user status into QuotaSnapshot')\n\n const snapshot: QuotaSnapshot = {\n timestamp: new Date().toISOString(),\n method: 'local',\n email: userStatus.email,\n models: []\n }\n\n // Parse prompt credits\n if (userStatus.quota?.promptCredits) {\n snapshot.promptCredits = parsePromptCredits(userStatus.quota.promptCredits)\n }\n\n // Parse models\n if (userStatus.quota?.models) {\n snapshot.models = userStatus.quota.models.map(parseModelQuota)\n }\n\n debug('local-parser', `Parsed ${snapshot.models.length} models`)\n return snapshot\n}\n\n/**\n * Parse prompt credits from Connect API format\n */\nfunction parsePromptCredits(credits: NonNullable<ConnectUserStatus['quota']>['promptCredits']): PromptCreditsInfo | undefined {\n if (!credits) {\n return undefined\n }\n\n const limit = credits.limit ?? 0\n const remaining = credits.remaining ?? limit\n const used = credits.used ?? (limit - remaining)\n\n if (limit === 0) {\n return undefined\n }\n\n const usedPercentage = limit > 0 ? used / limit : 0\n const remainingPercentage = limit > 0 ? remaining / limit : 1\n\n return {\n available: remaining,\n monthly: limit,\n usedPercentage,\n remainingPercentage\n }\n}\n\n/**\n * Parse a single model quota from Connect API format\n */\nfunction parseModelQuota(model: NonNullable<NonNullable<ConnectUserStatus['quota']>['models']>[number]): ModelQuotaInfo {\n const quota = model.quota\n\n return {\n label: model.label || model.displayName || model.modelId,\n modelId: model.modelId,\n remainingPercentage: quota?.remainingPercentage,\n isExhausted: model.isExhausted ?? (quota?.remainingPercentage === 0),\n resetTime: quota?.resetTime,\n timeUntilResetMs: quota?.timeUntilResetMs,\n isAutocompleteOnly: model.modelId.includes('gemini-2.5') ||\n (model.label || '').includes('Gemini 2.5') ||\n (model.displayName || '').includes('Gemini 2.5')\n }\n}\n","/**\n * Quota service - orchestrates fetching quota data\n */\n\nimport { debug } from '../core/logger.js'\nimport { getTokenManager } from '../google/token-manager.js'\nimport { CloudCodeClient, type FetchAvailableModelsResponse } from '../google/cloudcode.js'\nimport { parseQuotaSnapshot } from '../google/parser.js'\nimport { extractProjectId } from '../google/oauth.js'\nimport { \n detectAntigravityProcess, \n discoverPorts, \n probeForConnectAPI, \n ConnectClient, \n parseLocalQuotaSnapshot \n} from '../local/index.js'\nimport { \n AntigravityNotRunningError, \n LocalConnectionError, \n PortDetectionError,\n NoAuthMethodAvailableError\n} from '../core/errors.js'\nimport type { QuotaSnapshot } from './types.js'\n\nexport type QuotaMethod = 'google' | 'local' | 'auto'\n\n/**\n * Fetch quota using the specified method\n * @param method Method to use: 'auto' (default), 'google', or 'local'\n */\nexport async function fetchQuota(method: QuotaMethod = 'auto'): Promise<QuotaSnapshot> {\n if (method === 'auto') {\n try {\n debug('service', 'Auto mode: trying local method first')\n return await fetchQuotaLocal()\n } catch (err) {\n debug('service', 'Auto mode: local method failed', err)\n // Only fallback to Google if user is logged in\n const tokenManager = getTokenManager()\n if (tokenManager.isLoggedIn()) {\n debug('service', 'User is logged in, falling back to Google method')\n return fetchQuotaGoogle()\n }\n // User is not logged in and local failed - throw a helpful error\n throw new NoAuthMethodAvailableError()\n }\n }\n\n if (method === 'local') {\n return fetchQuotaLocal()\n }\n return fetchQuotaGoogle()\n}\n\n/**\n * Fetch quota from Google Cloud Code API\n */\nasync function fetchQuotaGoogle(): Promise<QuotaSnapshot> {\n debug('service', 'Fetching quota from Google')\n \n const tokenManager = getTokenManager()\n const email = tokenManager.getEmail()\n const client = new CloudCodeClient(tokenManager)\n \n // Fetch code assist (this one usually works)\n const codeAssistResponse = await client.loadCodeAssist()\n debug('service', 'Code assist response received', JSON.stringify(codeAssistResponse))\n \n // Save project ID to token storage for future use (for triggers, etc.)\n if (codeAssistResponse?.cloudaicompanionProject) {\n const projectId = extractProjectId(codeAssistResponse.cloudaicompanionProject)\n if (projectId) {\n tokenManager.setProjectId(projectId)\n debug('service', `Project ID saved: ${projectId}`)\n }\n }\n \n // Try to fetch models, but it might fail with 403\n let modelsResponse: FetchAvailableModelsResponse = {}\n try {\n modelsResponse = await client.fetchAvailableModels()\n debug('service', 'Models response received', JSON.stringify(modelsResponse))\n } catch (err) {\n debug('service', 'Failed to fetch models (might need different permissions)', err)\n // Continue without models - we'll still show prompt credits\n }\n \n // Parse into snapshot with email\n const snapshot = parseQuotaSnapshot(codeAssistResponse, modelsResponse, email)\n \n debug('service', 'Quota snapshot created')\n return snapshot\n}\n\n/**\n * Fetch quota from local Antigravity language server\n */\nasync function fetchQuotaLocal(): Promise<QuotaSnapshot> {\n debug('service', 'Fetching quota from local Antigravity server')\n \n // Step 1: Detect Antigravity process\n const processInfo = await detectAntigravityProcess()\n if (!processInfo) {\n throw new AntigravityNotRunningError()\n }\n \n debug('service', `Found Antigravity process: PID ${processInfo.pid}`)\n \n // Step 2: Discover all listening ports (to find the connect port, not extension_server_port)\n let ports = await discoverPorts(processInfo.pid)\n\n if (ports.length === 0 && processInfo.extensionServerPort) {\n debug('service', `Falling back to extension_server_port: ${processInfo.extensionServerPort}`)\n ports = [processInfo.extensionServerPort]\n }\n\n if (ports.length === 0) {\n throw new PortDetectionError()\n }\n \n debug('service', `Discovered ${ports.length} listening ports: ${ports.join(', ')}`)\n \n // Step 3: Probe ports to find Connect API (pass CSRF token for authentication)\n const probeResult = await probeForConnectAPI(ports, processInfo.csrfToken)\n if (!probeResult) {\n throw new LocalConnectionError('Could not find Antigravity Connect API on any port')\n }\n \n debug('service', `Found Connect API at ${probeResult.baseUrl}`)\n \n // Step 4: Connect to API and get user status\n const client = new ConnectClient(probeResult.baseUrl, processInfo.csrfToken)\n const userStatus = await client.getUserStatus()\n \n debug('service', 'User status received from local server')\n \n // Step 5: Parse into QuotaSnapshot\n const snapshot = parseLocalQuotaSnapshot(userStatus)\n \n debug('service', 'Local quota snapshot created')\n return snapshot\n}\n","/**\n * Quota output formatting\n */\n\nimport Table from 'cli-table3'\nimport type { QuotaSnapshot, ModelQuotaInfo } from './types.js'\n\n/**\n * Options for quota formatting\n */\nexport interface FormatOptions {\n allModels?: boolean\n}\n\n/**\n * Format milliseconds to human readable time\n */\nfunction formatTimeUntilReset(ms?: number): string {\n if (ms === undefined || ms <= 0) return 'N/A'\n\n const hours = Math.floor(ms / (1000 * 60 * 60))\n const minutes = Math.floor((ms % (1000 * 60 * 60)) / (1000 * 60))\n\n if (hours > 0) {\n return `${hours}h ${minutes}m`\n }\n return `${minutes}m`\n}\n\n/**\n * Format remaining percentage for display\n */\nfunction formatRemaining(model: ModelQuotaInfo): string {\n if (model.isExhausted) {\n return '❌ EXHAUSTED'\n }\n if (model.remainingPercentage === undefined) {\n return 'N/A'\n }\n\n const pct = Math.round(model.remainingPercentage * 100)\n if (pct >= 75) return `🟢 ${pct}%`\n if (pct >= 50) return `🟡 ${pct}%`\n if (pct >= 25) return `🟠 ${pct}%`\n return `🔴 ${pct}%`\n}\n\n/**\n * Print quota as a formatted table\n */\nexport function printQuotaTable(snapshot: QuotaSnapshot, options: FormatOptions = {}): void {\n const timestamp = new Date(snapshot.timestamp).toLocaleString()\n\n console.log()\n console.log(`📊 Antigravity Quota Status (via ${snapshot.method.toUpperCase()})`)\n console.log(` Retrieved: ${timestamp}`)\n\n // Display user info\n if (snapshot.email || snapshot.planType) {\n const userParts: string[] = []\n if (snapshot.email) {\n userParts.push(`👤 ${snapshot.email}`)\n }\n if (snapshot.planType) {\n userParts.push(`📋 Plan: ${snapshot.planType}`)\n }\n console.log(` ${userParts.join(' | ')}`)\n }\n\n const visibleModels = options.allModels\n ? snapshot.models\n : snapshot.models.filter(m => !m.isAutocompleteOnly)\n\n if (visibleModels.length > 0) {\n const table = new Table({\n head: ['Model', 'Remaining', 'Resets In'],\n style: {\n head: ['cyan'],\n border: ['gray']\n }\n })\n\n for (const model of visibleModels) {\n table.push([\n model.label,\n formatRemaining(model),\n formatTimeUntilReset(model.timeUntilResetMs)\n ])\n }\n\n console.log(table.toString())\n } else {\n console.log('No model quota information available.')\n if (!options.allModels && snapshot.models.some(m => m.isAutocompleteOnly)) {\n console.log('Tip: Use --all-models to see autocomplete models.')\n }\n }\n\n console.log()\n}\n\n/**\n * Print quota as JSON\n */\nexport function printQuotaJson(snapshot: QuotaSnapshot): void {\n console.log(JSON.stringify(snapshot, null, 2))\n}\n","/**\n * Table rendering utilities for multi-account displays\n */\n\nimport Table from 'cli-table3'\nimport type { AccountSummary } from '../accounts/types.js'\nimport type { QuotaSnapshot } from '../quota/types.js'\n\n/**\n * Format relative time (e.g., \"2 hours ago\")\n */\nfunction formatRelativeTime(isoDate: string | null): string {\n if (!isoDate) return 'Never'\n\n const date = new Date(isoDate)\n const now = Date.now()\n const diffMs = now - date.getTime()\n\n const minutes = Math.floor(diffMs / (1000 * 60))\n const hours = Math.floor(diffMs / (1000 * 60 * 60))\n const days = Math.floor(diffMs / (1000 * 60 * 60 * 24))\n\n if (minutes < 1) return 'Just now'\n if (minutes < 60) return `${minutes}m ago`\n if (hours < 24) return `${hours}h ago`\n if (days === 1) return 'Yesterday'\n return `${days} days ago`\n}\n\n/**\n * Format status icon\n */\nfunction formatStatus(status: string): string {\n switch (status) {\n case 'valid': return '✅'\n case 'expired': return '⚠️'\n case 'invalid': return '❌'\n default: return '❓'\n }\n}\n\n/**\n * Format credits display\n */\nfunction formatCredits(credits: { used: number; limit: number } | null | undefined): string {\n if (!credits) return '-'\n return `${credits.limit - credits.used} / ${credits.limit}`\n}\n\n/**\n * Render accounts list as a table\n */\nexport function renderAccountsTable(accounts: AccountSummary[]): void {\n if (accounts.length === 0) {\n console.log('\\n📭 No accounts found.')\n console.log('\\n💡 Run `antigravity-usage login` to add an account.\\n')\n return\n }\n\n console.log('\\n📊 Antigravity Accounts')\n console.log('═'.repeat(60))\n\n const totalWidth = process.stdout.columns || 80\n const isSmallTerminal = totalWidth < 90\n\n // Dynamic column widths\n // If small terminal, use tighter packing\n const colWidths = isSmallTerminal\n ? [25, 8, 12, 12] // Tighter widths for < 90 cols\n : [30, 10, 15, 15] // Standard widths\n\n // Ensure we don't exceed total width with borders (approx 10 chars)\n // If extremely small, let cli-table handle auto-sizing (pass undefined)\n const finalColWidths = totalWidth < 60 ? undefined : colWidths\n\n const tableOptions: any = {\n head: ['Account', 'Status', 'Credits', 'Last Used'],\n style: {\n head: ['cyan'],\n border: ['gray']\n }\n }\n\n if (finalColWidths) {\n tableOptions.colWidths = finalColWidths\n }\n\n const table = new Table(tableOptions)\n\n for (const account of accounts) {\n const nameDisplay = account.isActive\n ? `${account.email} [*]`\n : account.email\n\n table.push([\n nameDisplay,\n formatStatus(account.status),\n formatCredits(account.cachedCredits),\n formatRelativeTime(account.lastUsed)\n ])\n }\n\n console.log(table.toString())\n console.log('\\n[*] = active account\\n')\n}\n\n/**\n * Quota result for all accounts display\n */\nexport interface AllAccountsQuotaResult {\n email: string\n isActive: boolean\n status: 'success' | 'error' | 'cached'\n error?: string\n snapshot?: QuotaSnapshot\n cacheAge?: number\n}\n\n/**\n * Format quota remaining bar\n */\nfunction formatQuotaRemainingBar(remainingPercentage: number | undefined): string {\n const width = 10\n const filledChar = '█'\n const emptyChar = '░'\n\n if (remainingPercentage === undefined) {\n return `${emptyChar.repeat(width)} N/A`\n }\n\n const filled = Math.round((remainingPercentage / 100) * width)\n const empty = width - filled\n\n return `${filledChar.repeat(filled)}${emptyChar.repeat(empty)} ${Math.round(remainingPercentage)}%`\n}\n\n/**\n * Options for quota rendering\n */\nexport interface RenderOptions {\n allModels?: boolean\n}\n\n/**\n * Render quota for all accounts as a table\n */\nexport function renderAllQuotaTable(results: AllAccountsQuotaResult[], options: RenderOptions = {}): void {\n if (results.length === 0) {\n console.log('\\n📭 No accounts found.')\n console.log('\\n💡 Run `antigravity-usage login` to add an account.\\n')\n return\n }\n\n // Sort by quota remaining (highest to lowest)\n const sortedResults = [...results].sort((a, b) => {\n // Errors go last\n if (a.status === 'error' && b.status !== 'error') return 1\n if (a.status !== 'error' && b.status === 'error') return -1\n if (a.status === 'error' && b.status === 'error') return 0\n\n // Get remaining percentage for comparison\n const getRemaining = (result: AllAccountsQuotaResult): number => {\n // Filter out autocomplete models if requested\n const models = options.allModels\n ? result.snapshot?.models\n : result.snapshot?.models?.filter(m => !m.isAutocompleteOnly)\n\n const firstModel = models?.[0]\n if (!firstModel) return -1\n if (firstModel.isExhausted) return 0\n return firstModel.remainingPercentage ?? -1\n }\n\n const aRemaining = getRemaining(a)\n const bRemaining = getRemaining(b)\n\n // Sort descending (highest first)\n return bRemaining - aRemaining\n })\n\n console.log('\\n📊 Quota Overview - All Accounts')\n console.log('═'.repeat(70))\n\n const totalWidth = process.stdout.columns || 80\n\n // Calculate responsive widths\n // Standard: [30, 10, 15, 20] = ~75 content + 13 border = 88 chars\n\n let colWidths: number[] | undefined\n\n if (totalWidth < 80) {\n // Very small: auto-size or strict truncation\n colWidths = undefined\n } else if (totalWidth < 100) {\n // Compact mode\n colWidths = [25, 8, 12, 18]\n } else {\n // Spacious mode (fill remaining space with email column?)\n // For now keep standard spacious defaults\n colWidths = [30, 10, 15, 20]\n }\n\n const tableOptions: any = {\n head: ['Account', 'Source', 'Credits', 'Quota Remaining'],\n style: {\n head: ['cyan'],\n border: ['gray']\n }\n }\n\n if (colWidths) {\n tableOptions.colWidths = colWidths\n }\n\n const table = new Table(tableOptions)\n\n const errors: string[] = []\n\n for (const result of sortedResults) {\n const nameDisplay = result.isActive\n ? `${result.email} [*]`\n : result.email\n\n if (result.status === 'error') {\n table.push([\n nameDisplay,\n '-',\n '-',\n result.error || 'Error'\n ])\n errors.push(`${result.email}: ${result.error}`)\n } else {\n const snapshot = result.snapshot\n const source = result.status === 'cached'\n ? `Cached (${formatCacheAge(result.cacheAge)})`\n : (snapshot?.method.toUpperCase() || '-')\n\n // Get credits\n let credits = '-'\n if (snapshot?.promptCredits) {\n const pc = snapshot.promptCredits\n credits = `${pc.available} / ${pc.monthly}`\n }\n\n // Show the MINIMUM remaining percentage across relevant models\n // (This is the most constrained/concerning value for the user)\n let quotaRemaining = '-'\n const models = snapshot?.models || []\n const relevantModels = options.allModels\n ? models\n : models.filter(m => !m.isAutocompleteOnly)\n\n if (relevantModels.length > 0) {\n // Find minimum remaining percentage among relevant models\n const percentages = relevantModels\n .filter(m => m.remainingPercentage !== undefined)\n .map(m => m.remainingPercentage!)\n\n if (percentages.length > 0) {\n const minRemaining = Math.min(...percentages)\n quotaRemaining = formatQuotaRemainingBar(minRemaining * 100)\n } else if (relevantModels.some(m => m.isExhausted)) {\n quotaRemaining = '❌ EXHAUSTED'\n } else {\n quotaRemaining = formatQuotaRemainingBar(undefined)\n }\n }\n\n table.push([\n nameDisplay,\n source,\n credits,\n quotaRemaining\n ])\n }\n }\n\n console.log(table.toString())\n\n // Show errors if any\n if (errors.length > 0) {\n console.log(`\\n⚠️ ${errors.length} account(s) had errors:`)\n for (const err of errors) {\n console.log(` - ${err}`)\n }\n }\n\n console.log('\\n[*] = active account')\n console.log('💡 Use --refresh to fetch latest data\\n')\n}\n\nfunction formatCacheAge(seconds: number | undefined): string {\n if (seconds === undefined) return '?'\n if (seconds < 60) return `${seconds}s`\n if (seconds < 3600) return `${Math.floor(seconds / 60)}m`\n return `${Math.floor(seconds / 3600)}h`\n}\n","/**\n * Quota command - fetch and display quota information\n */\n\nimport { fetchQuota, type QuotaMethod } from '../quota/service.js'\nimport { printQuotaTable, printQuotaJson } from '../quota/format.js'\nimport { getTokenManager, getTokenManagerForAccount, resetTokenManager } from '../google/token-manager.js'\nimport { getAccountManager, saveCache, isCacheValid, loadCache, getCacheAge } from '../accounts/index.js'\nimport { renderAllQuotaTable, type AllAccountsQuotaResult } from '../render/index.js'\nimport { error as logError, debug, info } from '../core/logger.js'\nimport {\n NotLoggedInError,\n AuthenticationError,\n NetworkError,\n RateLimitError,\n APIError,\n AntigravityNotRunningError,\n LocalConnectionError,\n PortDetectionError,\n NoAuthMethodAvailableError\n} from '../core/errors.js'\n\ninterface QuotaOptions {\n json?: boolean\n method?: QuotaMethod\n all?: boolean\n account?: string\n refresh?: boolean\n allModels?: boolean\n}\n\n/**\n * Fetch quota for a single account\n */\nasync function fetchSingleAccountQuota(options: QuotaOptions): Promise<void> {\n // Determine which account to use\n const manager = getAccountManager()\n const accountEmail = options.account || manager.getActiveEmail()\n const originalActiveEmail = manager.getActiveEmail()\n\n // Force google method when --account is specified\n // (local method always uses IDE's logged-in account)\n let method = options.method || 'auto'\n if (options.account && method !== 'google') {\n debug('quota', `Account specified, forcing google method (local uses IDE account)`)\n method = 'google'\n }\n\n // Only check login for google method\n if (method === 'google') {\n const tokenManager = options.account\n ? getTokenManagerForAccount(options.account)\n : getTokenManager()\n\n if (!tokenManager.isLoggedIn()) {\n logError('Not logged in. Run: antigravity-usage login')\n process.exit(1)\n }\n }\n\n try {\n // Temporarily switch to the target account if needed\n let accountSwitched = false\n\n if (options.account && options.account !== originalActiveEmail) {\n debug('quota', `Temporarily switching to account ${options.account} for fetch`)\n manager.setActiveAccount(options.account)\n accountSwitched = true\n }\n\n try {\n debug('quota', `Fetching quota via ${method} method...`)\n const snapshot = await fetchQuota(method)\n\n // Cache the result if we have an account email\n if (accountEmail) {\n saveCache(accountEmail, snapshot)\n }\n\n if (options.json) {\n printQuotaJson(snapshot)\n } else {\n printQuotaTable(snapshot, { allModels: options.allModels })\n }\n } finally {\n // Always restore original active account\n if (accountSwitched && originalActiveEmail) {\n debug('quota', `Restoring active account to ${originalActiveEmail}`)\n manager.setActiveAccount(originalActiveEmail)\n }\n }\n } catch (err) {\n handleQuotaError(err)\n }\n}\n\n/**\n * Fetch quota for all accounts\n */\nasync function fetchAllAccountsQuota(options: QuotaOptions): Promise<void> {\n const manager = getAccountManager()\n const emails = manager.getAccountEmails()\n const activeEmail = manager.getActiveEmail()\n\n if (emails.length === 0) {\n logError('No accounts found. Run: antigravity-usage login')\n process.exit(1)\n }\n\n if (options.refresh) {\n info('🔄 Refreshing quota data for all accounts...\\n')\n }\n\n\n // IMPORTANT: Fetch sequentially, NOT in parallel\n // Parallel fetching causes race conditions with account switching\n const results: AllAccountsQuotaResult[] = []\n\n for (const email of emails) {\n const isActive = email === activeEmail\n\n try {\n // Check cache first (unless refresh requested)\n if (!options.refresh && isCacheValid(email)) {\n const cached = loadCache(email)\n if (cached) {\n debug('quota', `Using cached data for ${email}`)\n results.push({\n email,\n isActive,\n status: 'cached',\n snapshot: cached,\n cacheAge: getCacheAge(email) || 0\n })\n continue\n }\n }\n\n // Fetch fresh data\n debug('quota', `Fetching fresh data for ${email}`)\n\n const snapshot = await fetchQuotaForAccount(email, options.method || 'auto')\n\n // Cache the result\n saveCache(email, snapshot)\n\n results.push({\n email,\n isActive,\n status: 'success',\n snapshot\n })\n } catch (err) {\n debug('quota', `Error fetching quota for ${email}:`, err)\n\n // Try to use cached data on error\n const cached = loadCache(email)\n if (cached) {\n results.push({\n email,\n isActive,\n status: 'cached',\n snapshot: cached,\n cacheAge: getCacheAge(email) || 0\n })\n } else {\n results.push({\n email,\n isActive,\n status: 'error',\n error: err instanceof Error ? err.message : 'Unknown error'\n })\n }\n }\n }\n\n\n if (options.json) {\n console.log(JSON.stringify(results, null, 2))\n } else {\n renderAllQuotaTable(results, { allModels: options.allModels })\n }\n}\n\n/**\n * Fetch quota for a specific account\n */\nasync function fetchQuotaForAccount(email: string, method: QuotaMethod): Promise<any> {\n const manager = getAccountManager()\n const originalActiveEmail = manager.getActiveEmail()\n\n // CRITICAL: Local method always returns IDE's logged-in account data\n // We CANNOT use local method for non-IDE accounts in multi-account mode\n // Force Google API method to ensure we get the correct account's data\n let effectiveMethod = method\n\n if (method === 'auto' || method === 'local') {\n // Always use Google API for multi-account to avoid cache pollution\n effectiveMethod = 'google'\n debug('quota', `Forcing Google API for multi-account fetch (email: ${email})`)\n }\n\n // Temporarily switch to target account\n let accountSwitched = false\n if (email !== originalActiveEmail) {\n debug('quota', `Switching to ${email} for fetch`)\n manager.setActiveAccount(email)\n // CRITICAL: Reset TokenManager singleton so it loads the new account's tokens\n resetTokenManager()\n accountSwitched = true\n }\n\n try {\n const snapshot = await fetchQuota(effectiveMethod)\n return snapshot\n } finally {\n // Always restore original active account\n if (accountSwitched && originalActiveEmail) {\n debug('quota', `Restoring active account to ${originalActiveEmail}`)\n manager.setActiveAccount(originalActiveEmail)\n // Reset TokenManager again to pick up original account's tokens\n resetTokenManager()\n }\n }\n}\n\n/**\n * Handle quota errors\n */\nfunction handleQuotaError(err: unknown): never {\n // Auto mode: both methods unavailable\n if (err instanceof NoAuthMethodAvailableError) {\n logError(err.message)\n process.exit(1)\n }\n\n // Local method specific errors\n if (err instanceof AntigravityNotRunningError) {\n logError(err.message)\n console.log('\\nTip: Make sure Antigravity is running in your IDE (VSCode, etc.)')\n process.exit(1)\n }\n\n if (err instanceof LocalConnectionError) {\n logError(err.message)\n console.log('\\nTip: Try restarting your IDE or the Antigravity extension.')\n process.exit(1)\n }\n\n if (err instanceof PortDetectionError) {\n logError(err.message)\n console.log('\\nTip: This may happen if the Antigravity language server is still starting up.')\n process.exit(1)\n }\n\n // Google method specific errors\n if (err instanceof NotLoggedInError) {\n logError(err.message)\n process.exit(1)\n }\n\n if (err instanceof AuthenticationError) {\n logError(err.message)\n process.exit(1)\n }\n\n if (err instanceof NetworkError) {\n logError(err.message)\n process.exit(1)\n }\n\n if (err instanceof RateLimitError) {\n logError(err.message)\n if (err.retryAfterMs) {\n const seconds = Math.ceil(err.retryAfterMs / 1000)\n console.log(`Retry after ${seconds} seconds.`)\n }\n process.exit(1)\n }\n\n if (err instanceof APIError) {\n logError(err.message)\n process.exit(1)\n }\n\n // Unknown error\n logError(`Failed to fetch quota: ${err instanceof Error ? err.message : 'Unknown error'}`)\n debug('quota', 'Error details', err)\n process.exit(1)\n}\n\nexport async function quotaCommand(options: QuotaOptions): Promise<void> {\n if (options.all) {\n await fetchAllAccountsQuota(options)\n } else {\n await fetchSingleAccountQuota(options)\n }\n}\n","/**\n * Doctor command - diagnostics and troubleshooting\n */\n\nimport { getTokenManager } from '../google/token-manager.js'\nimport { getStorageInfo } from '../google/storage.js'\nimport { getConfigDir, getPlatform } from '../core/env.js'\nimport { maskEmail } from '../core/mask.js'\nimport { version } from '../version'\n\nexport function doctorCommand(): void {\n console.log()\n console.log('🩺 Antigravity Usage - Diagnostics')\n console.log('═'.repeat(50))\n console.log()\n \n // Version info\n console.log('📦 Version')\n console.log('─'.repeat(40))\n console.log(` CLI version: ${version}`)\n console.log(` Node.js: ${process.version}`)\n console.log(` Platform: ${getPlatform()}`)\n console.log()\n \n // Config paths\n const storage = getStorageInfo()\n console.log('📁 Configuration')\n console.log('─'.repeat(40))\n console.log(` Config dir: ${storage.configDir}`)\n console.log(` Tokens file: ${storage.tokensPath}`)\n console.log(` Tokens exist: ${storage.exists ? 'Yes' : 'No'}`)\n console.log()\n \n // Auth status\n const tokenManager = getTokenManager()\n console.log('🔐 Authentication')\n console.log('─'.repeat(40))\n \n if (!tokenManager.isLoggedIn()) {\n console.log(' Status: Not logged in')\n console.log()\n console.log(' 💡 Run `antigravity-usage login` to authenticate.')\n } else {\n console.log(' Status: Logged in')\n \n const email = tokenManager.getEmail()\n if (email) {\n console.log(` Email: ${maskEmail(email)}`)\n }\n \n const expiresAt = tokenManager.getExpiresAt()\n if (expiresAt) {\n const isExpired = tokenManager.isTokenExpired()\n console.log(` Token expires: ${expiresAt.toLocaleString()}`)\n console.log(` Token valid: ${isExpired ? 'No (needs refresh)' : 'Yes'}`)\n }\n }\n \n console.log()\n \n // Environment variables\n console.log('🔧 OAuth Configuration')\n console.log('─'.repeat(40))\n const hasClientId = !!process.env.ANTIGRAVITY_OAUTH_CLIENT_ID\n const hasClientSecret = !!process.env.ANTIGRAVITY_OAUTH_CLIENT_SECRET\n \n if (hasClientId || hasClientSecret) {\n console.log(' Using custom OAuth credentials:')\n console.log(` ANTIGRAVITY_OAUTH_CLIENT_ID: ${hasClientId ? 'Set' : 'Not set'}`)\n console.log(` ANTIGRAVITY_OAUTH_CLIENT_SECRET: ${hasClientSecret ? 'Set' : 'Not set'}`)\n } else {\n console.log(' ✅ Using built-in OAuth credentials')\n console.log(' 💡 Set ANTIGRAVITY_OAUTH_CLIENT_ID and ANTIGRAVITY_OAUTH_CLIENT_SECRET')\n console.log(' environment variables to use custom credentials.')\n }\n \n console.log()\n}\n","/**\n * Accounts command - manage multiple accounts\n */\n\nimport { getAccountManager } from '../accounts/index.js'\nimport { startOAuthFlow } from '../google/oauth.js'\nimport { getTokenManagerForAccount, resetTokenManager } from '../google/token-manager.js'\nimport { renderAccountsTable } from '../render/table.js'\nimport { success, warn, error as logError, info } from '../core/logger.js'\n\ninterface ListOptions {\n refresh?: boolean\n}\n\ninterface RemoveOptions {\n force?: boolean\n}\n\ninterface RefreshOptions {\n all?: boolean\n}\n\n/**\n * List all accounts\n */\nexport function listAccountsCommand(options: ListOptions): void {\n const manager = getAccountManager()\n const summaries = manager.getAccountSummaries()\n \n renderAccountsTable(summaries)\n \n if (options.refresh) {\n info('Use `antigravity-usage quota --all --refresh` to fetch fresh quota data.')\n }\n}\n\n/**\n * Add a new account (triggers OAuth flow)\n */\nexport async function addAccountCommand(): Promise<void> {\n info('Adding a new account...')\n \n const result = await startOAuthFlow()\n \n if (result.success) {\n success(`Account added successfully${result.email ? `: ${result.email}` : ''}!`)\n \n // Show updated account list\n const manager = getAccountManager()\n const summaries = manager.getAccountSummaries()\n console.log('\\nYour accounts:')\n renderAccountsTable(summaries)\n } else {\n logError(`Failed to add account: ${result.error}`)\n process.exit(1)\n }\n}\n\n/**\n * Switch active account\n */\nexport function switchAccountCommand(email: string): void {\n const manager = getAccountManager()\n \n // Check if account exists\n if (!manager.hasAccount(email)) {\n logError(`Account '${email}' not found.`)\n \n const emails = manager.getAccountEmails()\n if (emails.length > 0) {\n console.log('\\nAvailable accounts:')\n for (const e of emails) {\n console.log(` - ${e}`)\n }\n } else {\n info('\\nNo accounts found. Run `antigravity-usage login` to add one.')\n }\n \n process.exit(1)\n }\n \n // Switch account\n const switched = manager.setActiveAccount(email)\n \n if (switched) {\n success(`Switched to account: ${email}`)\n } else {\n logError(`Failed to switch to account: ${email}`)\n process.exit(1)\n }\n}\n\n/**\n * Remove an account\n */\nexport function removeAccountCommand(email: string, options: RemoveOptions): void {\n const manager = getAccountManager()\n \n // Check if account exists\n if (!manager.hasAccount(email)) {\n logError(`Account '${email}' not found.`)\n process.exit(1)\n }\n \n // Confirmation warning (unless --force)\n if (!options.force) {\n warn(`This will remove account '${email}' and all its data.`)\n info('Use --force to skip this warning.')\n // In a real CLI, we'd prompt for confirmation here\n // For now, just proceed\n }\n \n const removed = manager.removeAccount(email)\n \n if (removed) {\n success(`Account '${email}' removed.`)\n \n // Show remaining accounts\n const remaining = manager.getAccountEmails()\n if (remaining.length > 0) {\n const active = manager.getActiveEmail()\n console.log(`\\nActive account: ${active || 'none'}`)\n console.log(`Remaining accounts: ${remaining.length}`)\n } else {\n info('\\nNo accounts remaining. Run `antigravity-usage login` to add one.')\n }\n } else {\n logError(`Failed to remove account: ${email}`)\n process.exit(1)\n }\n}\n\n/**\n * Show current active account\n */\nexport function currentAccountCommand(): void {\n const manager = getAccountManager()\n const active = manager.getActiveEmail()\n \n if (active) {\n console.log()\n console.log(`📍 Active account: ${active}`)\n \n // Get account info\n const info = manager.getAccountInfo(active)\n if (info) {\n const statusIcon = info.status === 'valid' ? '✅' : \n info.status === 'expired' ? '⚠️' : '❌'\n console.log(` Status: ${statusIcon} ${info.status}`)\n \n if (info.tokens?.expiresAt) {\n const expiresAt = new Date(info.tokens.expiresAt).toLocaleString()\n console.log(` Token expires: ${expiresAt}`)\n }\n }\n console.log()\n } else {\n warn('No active account set.')\n \n const emails = manager.getAccountEmails()\n if (emails.length > 0) {\n console.log('\\nAvailable accounts:')\n for (const e of emails) {\n console.log(` - ${e}`)\n }\n info('\\nRun `antigravity-usage accounts switch <email>` to set an active account.')\n } else {\n info('\\nRun `antigravity-usage login` to add an account.')\n }\n }\n}\n\n/**\n * Refresh account tokens\n */\nexport async function refreshAccountCommand(email: string | undefined, options: RefreshOptions): Promise<void> {\n const manager = getAccountManager()\n \n // Refresh all accounts\n if (options.all) {\n const emails = manager.getAccountEmails()\n \n if (emails.length === 0) {\n warn('No accounts to refresh.')\n return\n }\n \n console.log(`\\n🔄 Refreshing ${emails.length} account(s)...\\n`)\n \n let successCount = 0\n let failCount = 0\n \n for (const e of emails) {\n try {\n const tokenManager = getTokenManagerForAccount(e)\n if (tokenManager.isTokenExpired()) {\n await tokenManager.refreshToken()\n success(` ✅ ${e}`)\n successCount++\n } else {\n info(` ⏭️ ${e} (token still valid)`)\n successCount++\n }\n } catch (err) {\n logError(` ❌ ${e}: ${err instanceof Error ? err.message : 'Failed'}`)\n failCount++\n }\n }\n \n resetTokenManager()\n \n console.log()\n if (failCount > 0) {\n warn(`${failCount} account(s) need re-authentication. Run: antigravity-usage login`)\n } else {\n success(`All ${successCount} account(s) refreshed successfully!`)\n }\n return\n }\n \n // Refresh specific or active account\n const targetEmail = email || manager.getActiveEmail()\n \n if (!targetEmail) {\n logError('No account specified and no active account.')\n info('Usage: antigravity-usage accounts refresh <email>')\n info(' or: antigravity-usage accounts refresh --all')\n process.exit(1)\n }\n \n if (!manager.hasAccount(targetEmail)) {\n logError(`Account '${targetEmail}' not found.`)\n process.exit(1)\n }\n \n console.log(`\\n🔄 Refreshing ${targetEmail}...`)\n \n try {\n const tokenManager = getTokenManagerForAccount(targetEmail)\n \n if (!tokenManager.isTokenExpired()) {\n info(`Token for ${targetEmail} is still valid.`)\n return\n }\n \n await tokenManager.refreshToken()\n resetTokenManager()\n success(`\\n✅ Token refreshed for ${targetEmail}`)\n } catch (err) {\n logError(`\\n❌ Failed to refresh token: ${err instanceof Error ? err.message : 'Unknown error'}`)\n info('\\nThe refresh token may be expired. Please re-authenticate:')\n info(` antigravity-usage accounts switch ${targetEmail}`)\n info(' antigravity-usage login')\n process.exit(1)\n }\n}\n\n/**\n * Main accounts command handler - dispatches to subcommands\n */\nexport async function accountsCommand(\n subcommand: string,\n args: string[],\n options: { refresh?: boolean; force?: boolean; all?: boolean }\n): Promise<void> {\n switch (subcommand) {\n case 'list':\n listAccountsCommand({ refresh: options.refresh })\n break\n \n case 'add':\n await addAccountCommand()\n break\n \n case 'switch':\n if (!args[0]) {\n logError('Please specify an account email to switch to.')\n console.log('Usage: antigravity-usage accounts switch <email>')\n process.exit(1)\n }\n switchAccountCommand(args[0])\n break\n \n case 'remove':\n if (!args[0]) {\n logError('Please specify an account email to remove.')\n console.log('Usage: antigravity-usage accounts remove <email>')\n process.exit(1)\n }\n removeAccountCommand(args[0], { force: options.force })\n break\n \n case 'current':\n currentAccountCommand()\n break\n \n case 'refresh':\n await refreshAccountCommand(args[0], { all: options.all })\n break\n \n default:\n // Default to list if no subcommand\n listAccountsCommand({ refresh: options.refresh })\n }\n}\n","/**\n * Wakeup command - Auto wake-up and warm up AI models\n */\n\nimport inquirer from 'inquirer'\nimport Table from 'cli-table3'\nimport {\n loadWakeupConfig,\n saveWakeupConfig,\n getOrCreateConfig,\n getRecentHistory,\n getLastTrigger,\n clearTriggerHistory,\n type WakeupConfig,\n type TriggerRecord,\n getDefaultConfig\n} from '../wakeup/index.js'\nimport {\n installCronJob,\n uninstallCronJob,\n getCronStatus,\n isCronSupported\n} from '../wakeup/cron-installer.js'\nimport {\n configToCronExpression,\n getScheduleDescription,\n getNextRunEstimate\n} from '../wakeup/schedule-converter.js'\nimport {\n executeTrigger,\n testTrigger\n} from '../wakeup/trigger-service.js'\nimport {\n resolveAccounts,\n getAccountResolutionStatus\n} from '../wakeup/account-resolver.js'\nimport { getAccountManager } from '../accounts/manager.js'\nimport { debug } from '../core/logger.js'\n\n// Subcommand type\ntype WakeupSubcommand = 'config' | 'trigger' | 'install' | 'uninstall' | 'test' | 'history' | 'status'\n\ninterface WakeupOptions {\n scheduled?: boolean\n limit?: string\n json?: boolean\n email?: string\n model?: string\n prompt?: string\n}\n\n/**\n * Main wakeup command handler\n */\nexport async function wakeupCommand(\n subcommand: WakeupSubcommand,\n args: string[],\n options: WakeupOptions\n): Promise<void> {\n debug('wakeup', `Subcommand: ${subcommand}, options:`, options)\n \n switch (subcommand) {\n case 'config':\n await configureWakeup()\n break\n \n case 'trigger':\n await runScheduledTrigger(options.scheduled ?? false)\n break\n \n case 'install':\n await installSchedule()\n break\n \n case 'uninstall':\n await uninstallSchedule()\n break\n \n case 'test':\n await runTestTrigger(options)\n break\n \n case 'history':\n await showHistory(options)\n break\n \n case 'status':\n default:\n await showStatus()\n break\n }\n}\n\n// ============================================================================\n// Subcommand Implementations\n// ============================================================================\n\n/**\n * Configure wake-up schedule interactively\n */\nasync function configureWakeup(): Promise<void> {\n console.log('\\n🔧 Auto Wake-up Configuration\\n')\n \n const config = getOrCreateConfig()\n const accountManager = getAccountManager()\n const accounts = accountManager.getAccountEmails()\n \n if (accounts.length === 0) {\n console.log('❌ No accounts available. Please login first:')\n console.log(' antigravity-usage login\\n')\n return\n }\n \n // Step 1: Enable/disable\n const { enabled } = await inquirer.prompt([{\n type: 'confirm',\n name: 'enabled',\n message: 'Enable auto wake-up?',\n default: config.enabled\n }])\n \n if (!enabled) {\n config.enabled = false\n saveWakeupConfig(config)\n console.log('\\n✅ Auto wake-up disabled')\n return\n }\n \n // Step 2: Choose trigger mode\n const { triggerMode } = await inquirer.prompt([{\n type: 'list',\n name: 'triggerMode',\n message: 'Trigger mode:',\n choices: [\n { name: 'Schedule-based (run at specific times)', value: 'schedule' },\n { name: 'Quota-reset-based (trigger when quota resets)', value: 'reset' }\n ],\n default: config.wakeOnReset ? 'reset' : 'schedule'\n }])\n \n config.wakeOnReset = triggerMode === 'reset'\n \n // Step 3: Configure schedule (if schedule mode)\n if (!config.wakeOnReset) {\n const { scheduleMode } = await inquirer.prompt([{\n type: 'list',\n name: 'scheduleMode',\n message: 'Schedule type:',\n choices: [\n { name: 'Every N hours', value: 'interval' },\n { name: 'Daily at specific times', value: 'daily' },\n { name: 'Custom cron expression', value: 'custom' }\n ],\n default: config.scheduleMode\n }])\n \n config.scheduleMode = scheduleMode\n \n if (scheduleMode === 'interval') {\n const { intervalHours } = await inquirer.prompt([{\n type: 'number',\n name: 'intervalHours',\n message: 'Trigger every N hours:',\n default: config.intervalHours || 6,\n validate: (val: number) => val >= 1 && val <= 23 ? true : 'Must be 1-23'\n }])\n config.intervalHours = intervalHours\n } else if (scheduleMode === 'daily') {\n const { dailyTime } = await inquirer.prompt([{\n type: 'input',\n name: 'dailyTime',\n message: 'Time to trigger (HH:MM):',\n default: config.dailyTimes?.[0] || '09:00',\n validate: (val: string) => /^\\d{1,2}:\\d{2}$/.test(val) ? true : 'Use HH:MM format'\n }])\n config.dailyTimes = [dailyTime]\n } else if (scheduleMode === 'custom') {\n const { cronExpression } = await inquirer.prompt([{\n type: 'input',\n name: 'cronExpression',\n message: 'Cron expression (min hour day month weekday):',\n default: config.cronExpression || '0 */6 * * *'\n }])\n config.cronExpression = cronExpression\n }\n } else {\n // Reset mode configuration\n const { resetCooldown } = await inquirer.prompt([{\n type: 'number',\n name: 'resetCooldown',\n message: 'Cooldown between triggers (minutes):',\n default: config.resetCooldownMinutes || 10,\n validate: (val: number) => val >= 1 ? true : 'Must be at least 1 minute'\n }])\n config.resetCooldownMinutes = resetCooldown\n }\n \n // Step 4: Models - Use default models that cover both families\n // claude-sonnet-4-5 triggers Claude family\n // gemini-3-flash and gemini-3-pro-low trigger both Gemini quota groups\n config.selectedModels = ['claude-sonnet-4-5', 'gemini-3-flash', 'gemini-3-pro-low']\n console.log('\\n 📦 Models: claude-sonnet-4-5, gemini-3-flash, gemini-3-pro-low')\n console.log(' (Triggers both Claude and Gemini families)')\n \n // Step 5: Select accounts\n if (accounts.length > 1) {\n const { selectedAccounts } = await inquirer.prompt([{\n type: 'checkbox',\n name: 'selectedAccounts',\n message: 'Select accounts to use:',\n choices: accounts.map(email => ({\n name: email,\n value: email,\n checked: !config.selectedAccounts || config.selectedAccounts.includes(email)\n }))\n }])\n config.selectedAccounts = selectedAccounts.length > 0 ? selectedAccounts : undefined\n } else {\n config.selectedAccounts = undefined // Use default (active account)\n }\n \n // Step 6: Custom prompt (optional)\n const { customPrompt } = await inquirer.prompt([{\n type: 'input',\n name: 'customPrompt',\n message: 'Custom wake-up prompt (leave empty for default \"hi\"):',\n default: config.customPrompt || ''\n }])\n config.customPrompt = customPrompt || undefined\n \n // Step 7: Max output tokens\n const { maxTokens } = await inquirer.prompt([{\n type: 'number',\n name: 'maxTokens',\n message: 'Max output tokens (0 = no limit):',\n default: config.maxOutputTokens || 0\n }])\n config.maxOutputTokens = maxTokens\n \n // Save config\n config.enabled = true\n saveWakeupConfig(config)\n \n console.log('\\n✅ Configuration saved!')\n console.log(` Mode: ${getScheduleDescription(config)}`)\n console.log(` Models: ${config.selectedModels.join(', ')}`)\n console.log(` Accounts: ${config.selectedAccounts?.join(', ') || 'Active account'}`)\n \n // Offer to install cron job if schedule mode\n if (!config.wakeOnReset && isCronSupported()) {\n const { installNow } = await inquirer.prompt([{\n type: 'confirm',\n name: 'installNow',\n message: 'Install to system cron now?',\n default: true\n }])\n \n if (installNow) {\n await installSchedule()\n } else {\n console.log('\\n📋 To install later, run:')\n console.log(' antigravity-usage wakeup install')\n }\n }\n \n console.log('')\n}\n\n/**\n * Run a scheduled trigger (called by cron)\n */\nasync function runScheduledTrigger(isScheduled: boolean): Promise<void> {\n debug('wakeup', `Running trigger (scheduled: ${isScheduled})`)\n \n const config = loadWakeupConfig()\n \n if (!config || !config.enabled) {\n debug('wakeup', 'Wakeup not configured or disabled')\n return\n }\n \n const accounts = resolveAccounts(config.selectedAccounts)\n if (accounts.length === 0) {\n debug('wakeup', 'No valid accounts')\n return\n }\n \n if (config.selectedModels.length === 0) {\n debug('wakeup', 'No models selected')\n return\n }\n \n // Execute trigger for each account\n for (const accountEmail of accounts) {\n const result = await executeTrigger({\n models: config.selectedModels,\n accountEmail,\n triggerType: 'auto',\n triggerSource: isScheduled ? 'scheduled' : 'manual',\n customPrompt: config.customPrompt,\n maxOutputTokens: config.maxOutputTokens\n })\n \n const successCount = result.results.filter(r => r.success).length\n console.log(`[${new Date().toISOString()}] ${accountEmail}: ${successCount}/${result.results.length} models triggered`)\n }\n}\n\n/**\n * Install schedule to system cron\n */\nasync function installSchedule(): Promise<void> {\n console.log('\\n📅 Installing wake-up schedule to cron...\\n')\n \n if (!isCronSupported()) {\n console.log('❌ Cron is not supported on this platform.')\n console.log(' Windows Task Scheduler support coming soon.')\n return\n }\n \n const config = loadWakeupConfig()\n \n if (!config) {\n console.log('❌ No wake-up configuration found.')\n console.log(' Run: antigravity-usage wakeup config')\n return\n }\n \n if (!config.enabled) {\n console.log('❌ Wake-up is disabled. Enable it first:')\n console.log(' antigravity-usage wakeup config')\n return\n }\n \n if (config.wakeOnReset) {\n console.log('ℹ️ Quota-reset mode does not require cron installation.')\n console.log(' Triggers happen automatically when you check quota.')\n return\n }\n \n try {\n const cronExpression = configToCronExpression(config)\n console.log(` Schedule: ${getScheduleDescription(config)}`)\n console.log(` Cron: ${cronExpression}`)\n console.log('')\n \n const result = await installCronJob(cronExpression)\n \n if (result.success) {\n console.log('✅ Cron job installed successfully!')\n console.log(` Next run: ${getNextRunEstimate(cronExpression)}`)\n console.log('')\n console.log(' To check status: antigravity-usage wakeup status')\n console.log(' To uninstall: antigravity-usage wakeup uninstall')\n } else {\n console.log('⚠️ Automatic installation failed.')\n if (result.manualInstructions) {\n console.log('')\n console.log(result.manualInstructions)\n }\n }\n } catch (err) {\n console.log(`❌ Error: ${err instanceof Error ? err.message : err}`)\n }\n \n console.log('')\n}\n\n/**\n * Uninstall schedule from system cron\n */\nasync function uninstallSchedule(): Promise<void> {\n console.log('\\n🗑️ Removing wake-up schedule from cron...\\n')\n \n const success = await uninstallCronJob()\n \n if (success) {\n console.log('✅ Cron job removed successfully!')\n } else {\n console.log('⚠️ Could not remove cron job. It may not be installed.')\n console.log(' Check your crontab: crontab -l')\n }\n \n console.log('')\n}\n\n/**\n * Run a manual test trigger\n */\nasync function runTestTrigger(options: WakeupOptions = {}): Promise<void> {\n console.log('\\n🧪 Test Trigger\\n')\n \n const accountManager = getAccountManager()\n const accounts = accountManager.getAccountEmails()\n \n if (accounts.length === 0) {\n console.log('❌ No accounts available. Please login first.')\n return\n }\n \n // Select account\n let accountEmail: string\n if (options.email) {\n // Validate provided email\n if (!accounts.includes(options.email)) {\n console.log(`❌ Account \"${options.email}\" not found.`)\n console.log(` Available accounts: ${accounts.join(', ')}`)\n return\n }\n accountEmail = options.email\n } else if (accounts.length === 1) {\n accountEmail = accounts[0]\n } else {\n const { selectedAccount } = await inquirer.prompt([{\n type: 'list',\n name: 'selectedAccount',\n message: 'Select account:',\n choices: accounts\n }])\n accountEmail = selectedAccount\n }\n \n // Enter model ID\n let modelId: string\n if (options.model) {\n modelId = options.model\n } else {\n const config = loadWakeupConfig()\n const { selectedModel } = await inquirer.prompt([{\n type: 'input',\n name: 'selectedModel',\n message: 'Model ID to test:',\n default: config?.selectedModels[0] || 'claude-sonnet-4-5'\n }])\n modelId = selectedModel\n }\n \n // Enter prompt\n const prompt = options.prompt || 'hi'\n \n console.log('\\n⏳ Triggering...')\n \n try {\n const result = await testTrigger(modelId, accountEmail, prompt)\n \n if (result.success) {\n console.log(`\\n✅ Success! (${result.durationMs}ms)`)\n if (result.response) {\n console.log(`\\n📝 Response:\\n${result.response.substring(0, 200)}...`)\n }\n if (result.tokensUsed) {\n console.log(`\\n📊 Tokens: ${result.tokensUsed.total} (prompt: ${result.tokensUsed.prompt}, completion: ${result.tokensUsed.completion})`)\n }\n } else {\n console.log(`\\n❌ Failed: ${result.error}`)\n }\n } catch (err) {\n console.log(`\\n❌ Error: ${err instanceof Error ? err.message : err}`)\n }\n \n console.log('')\n \n // Exit cleanly to avoid hanging on open HTTP connections\n process.exit(0)\n}\n\n/**\n * Show trigger history\n */\nasync function showHistory(options: WakeupOptions): Promise<void> {\n const limit = parseInt(options.limit || '10', 10)\n const history = getRecentHistory(limit)\n \n if (history.length === 0) {\n console.log('\\n📜 No trigger history yet.\\n')\n return\n }\n \n if (options.json) {\n console.log(JSON.stringify(history, null, 2))\n return\n }\n \n console.log(`\\n📜 Trigger History (last ${Math.min(limit, history.length)} records)\\n`)\n \n const table = new Table({\n head: ['Time', 'Source', 'Model', 'Account', 'Duration', 'Status'],\n style: { head: ['cyan'] }\n })\n \n for (const record of history) {\n const time = new Date(record.timestamp).toLocaleString()\n const status = record.success ? '✅' : `❌ ${record.error?.substring(0, 20) || ''}`\n \n table.push([\n time,\n record.triggerSource,\n record.models[0] || '-',\n record.accountEmail.split('@')[0],\n `${record.durationMs}ms`,\n status\n ])\n }\n \n console.log(table.toString())\n console.log('')\n}\n\n/**\n * Show current wake-up status\n */\nasync function showStatus(): Promise<void> {\n console.log('\\n📊 Auto Wake-up Status\\n')\n \n const config = loadWakeupConfig()\n \n if (!config) {\n console.log(' Status: Not configured')\n console.log('')\n console.log(' To configure: antigravity-usage wakeup config')\n console.log('')\n return\n }\n \n // Basic status\n console.log(` Enabled: ${config.enabled ? '✅ Yes' : '❌ No'}`)\n console.log(` Mode: ${getScheduleDescription(config)}`)\n \n // Models\n if (config.selectedModels.length > 0) {\n console.log(` Models: ${config.selectedModels.join(', ')}`)\n } else {\n console.log(' Models: None selected')\n }\n \n // Accounts\n console.log(` Accounts: ${getAccountResolutionStatus(config.selectedAccounts)}`)\n \n // Cron status (for schedule mode)\n if (!config.wakeOnReset && config.enabled) {\n const cronStatus = await getCronStatus()\n if (cronStatus.installed) {\n console.log(` Cron: ✅ Installed (${cronStatus.cronExpression})`)\n if (cronStatus.nextRun) {\n console.log(` Next run: ${cronStatus.nextRun}`)\n }\n } else {\n console.log(' Cron: ❌ Not installed')\n console.log(' Run: antigravity-usage wakeup install')\n }\n }\n \n // Last trigger\n const lastTrigger = getLastTrigger()\n if (lastTrigger) {\n const ago = getTimeAgo(new Date(lastTrigger.timestamp))\n const status = lastTrigger.success ? '✅ success' : `❌ ${lastTrigger.error?.substring(0, 30) || 'failed'}`\n console.log(` Last trigger: ${ago} (${status})`)\n } else {\n console.log(' Last trigger: Never')\n }\n \n console.log('')\n}\n\n/**\n * Get human-readable time ago string\n */\nfunction getTimeAgo(date: Date): string {\n const seconds = Math.floor((Date.now() - date.getTime()) / 1000)\n \n if (seconds < 60) return 'Just now'\n if (seconds < 3600) return `${Math.floor(seconds / 60)} minutes ago`\n if (seconds < 86400) return `${Math.floor(seconds / 3600)} hours ago`\n return `${Math.floor(seconds / 86400)} days ago`\n}\n","/**\n * Auto Wake-up types\n * Types for schedule configuration, trigger history, and reset state\n */\n\n// ============================================================================\n// Schedule Configuration\n// ============================================================================\n\n/**\n * Main wake-up configuration\n */\nexport interface WakeupConfig {\n // Global settings\n enabled: boolean\n selectedModels: string[] // Model IDs to trigger\n selectedAccounts?: string[] // Account emails (undefined = use active)\n customPrompt?: string // Optional custom wake-up prompt\n maxOutputTokens: number // 0 = no limit\n \n // Schedule-based mode\n scheduleMode: ScheduleMode\n intervalHours?: number // For interval mode (e.g., 6 = every 6 hours)\n dailyTimes?: string[] // For daily mode: [\"09:00\", \"17:00\"]\n weeklySchedule?: WeeklySchedule // For weekly mode\n cronExpression?: string // For custom mode (advanced users)\n \n // Quota-reset mode\n wakeOnReset: boolean // Enable quota-reset-based triggering\n resetCooldownMinutes: number // Cooldown between reset triggers (default: 10)\n}\n\n/**\n * Weekly schedule - maps day number to array of times\n * Day numbers: 0=Sunday, 1=Monday, ..., 6=Saturday\n */\nexport interface WeeklySchedule {\n [day: number]: string[]\n}\n\n/**\n * Schedule mode types\n */\nexport type ScheduleMode = 'interval' | 'daily' | 'weekly' | 'custom'\n\n/**\n * Default configuration\n * \n * Default models trigger both Claude and Gemini families:\n * - claude-sonnet-4-5: Wakes up Claude family\n * - gemini-3-flash: Wakes up Gemini flash quota group\n * - gemini-3-pro-low: Wakes up Gemini pro quota group\n */\nexport function getDefaultConfig(): WakeupConfig {\n return {\n enabled: false,\n selectedModels: ['claude-sonnet-4-5', 'gemini-3-flash', 'gemini-3-pro-low'],\n selectedAccounts: undefined,\n customPrompt: undefined,\n maxOutputTokens: 1, // Minimal tokens to save quota\n scheduleMode: 'interval',\n intervalHours: 6,\n dailyTimes: ['09:00'],\n weeklySchedule: {},\n cronExpression: undefined,\n wakeOnReset: false,\n resetCooldownMinutes: 10\n }\n}\n\n// ============================================================================\n// Trigger History\n// ============================================================================\n\n/**\n * Trigger type - manual (user initiated) or auto (scheduled/reset-based)\n */\nexport type TriggerType = 'manual' | 'auto'\n\n/**\n * Trigger source - how the trigger was initiated\n */\nexport type TriggerSource = 'manual' | 'scheduled' | 'quota_reset'\n\n/**\n * Token usage information from API response\n */\nexport interface TokenUsage {\n prompt: number\n completion: number\n total: number\n}\n\n/**\n * Single trigger history record\n */\nexport interface TriggerRecord {\n timestamp: string // ISO timestamp\n success: boolean\n triggerType: TriggerType\n triggerSource: TriggerSource\n models: string[] // Model IDs triggered\n accountEmail: string\n durationMs: number\n prompt: string // Actual prompt used\n response?: string // AI response (truncated to 500 chars)\n error?: string // Error message if failed\n tokensUsed?: TokenUsage\n}\n\n// ============================================================================\n// Reset Detection State\n// ============================================================================\n\n/**\n * State for a single model's reset tracking\n */\nexport interface ModelResetState {\n lastResetAt: string // Last resetAt timestamp we triggered for\n lastTriggeredTime: string // When we last triggered (ISO timestamp)\n}\n\n/**\n * Reset deduplication state - keyed by model reset key\n * Key is modelConstant if available, otherwise modelId\n */\nexport interface ResetState {\n [modelResetKey: string]: ModelResetState\n}\n\n// ============================================================================\n// Model Mapping\n// ============================================================================\n\n/**\n * Mapping from model ID to model constant\n * Used for quota reset deduplication\n */\nexport interface ModelMapping {\n [modelId: string]: string\n}\n\n// ============================================================================\n// Trigger Service Types\n// ============================================================================\n\n/**\n * Options for executing a trigger\n */\nexport interface TriggerOptions {\n models: string[] // Model IDs to trigger\n accountEmail: string // Which account to use\n triggerType: TriggerType\n triggerSource: TriggerSource\n customPrompt?: string\n maxOutputTokens?: number // 0 = no limit\n}\n\n/**\n * Result from triggering a single model\n */\nexport interface ModelTriggerResult {\n modelId: string\n success: boolean\n durationMs: number\n response?: string\n error?: string\n tokensUsed?: TokenUsage\n}\n\n/**\n * Overall trigger execution result\n */\nexport interface TriggerResult {\n success: boolean // True if all models succeeded\n results: ModelTriggerResult[]\n}\n\n// ============================================================================\n// Cron Installer Types\n// ============================================================================\n\n/**\n * Result from cron installation attempt\n */\nexport interface CronInstallResult {\n success: boolean\n cronExpression?: string\n manualInstructions?: string // Fallback instructions if auto-install fails\n error?: string\n}\n\n/**\n * Status of cron installation\n */\nexport interface CronStatus {\n installed: boolean\n cronExpression?: string\n nextRun?: string // Human-readable next run time\n}\n\n// ============================================================================\n// Reset Detection Types\n// ============================================================================\n\n/**\n * Result from reset detection\n */\nexport interface DetectionResult {\n triggered: boolean\n triggeredModels: string[]\n}\n","/**\n * Auto Wake-up storage service\n * Handles persistence of config, trigger history, reset state, and model mappings\n */\n\nimport { join } from 'path'\nimport { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'\nimport { debug } from '../core/logger.js'\nimport { getConfigDir } from '../core/env.js'\nimport type { \n WakeupConfig, \n TriggerRecord, \n ResetState,\n ModelMapping \n} from './types.js'\nimport { getDefaultConfig } from './types.js'\n\n// Storage paths\nconst WAKEUP_DIR_NAME = 'wakeup'\nconst CONFIG_FILE_NAME = 'config.json'\nconst HISTORY_FILE_NAME = 'history.json'\nconst RESET_STATE_FILE_NAME = 'reset-state.json'\nconst MODEL_MAPPING_FILE_NAME = 'model-mapping.json'\n\n// History ring buffer size\nconst MAX_HISTORY_ENTRIES = 100\n\n/**\n * Get wakeup storage directory path\n */\nfunction getWakeupDir(): string {\n return join(getConfigDir(), WAKEUP_DIR_NAME)\n}\n\n/**\n * Ensure wakeup directory exists\n */\nfunction ensureWakeupDir(): void {\n const dir = getWakeupDir()\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n debug('wakeup-storage', `Created wakeup directory: ${dir}`)\n }\n}\n\n/**\n * Generic JSON file reader\n */\nfunction readJsonFile<T>(filename: string, defaultValue: T): T {\n const filepath = join(getWakeupDir(), filename)\n try {\n if (existsSync(filepath)) {\n const content = readFileSync(filepath, 'utf-8')\n return JSON.parse(content) as T\n }\n } catch (err) {\n debug('wakeup-storage', `Error reading ${filename}:`, err)\n }\n return defaultValue\n}\n\n/**\n * Generic JSON file writer\n */\nfunction writeJsonFile<T>(filename: string, data: T): void {\n ensureWakeupDir()\n const filepath = join(getWakeupDir(), filename)\n try {\n writeFileSync(filepath, JSON.stringify(data, null, 2), 'utf-8')\n debug('wakeup-storage', `Wrote ${filename}`)\n } catch (err) {\n debug('wakeup-storage', `Error writing ${filename}:`, err)\n throw err\n }\n}\n\n// ============================================================================\n// Config Operations\n// ============================================================================\n\n/**\n * Load wake-up configuration\n * Returns null if no config exists\n */\nexport function loadWakeupConfig(): WakeupConfig | null {\n const config = readJsonFile<WakeupConfig | null>(CONFIG_FILE_NAME, null)\n if (config) {\n debug('wakeup-storage', 'Loaded wakeup config')\n }\n return config\n}\n\n/**\n * Save wake-up configuration\n */\nexport function saveWakeupConfig(config: WakeupConfig): void {\n writeJsonFile(CONFIG_FILE_NAME, config)\n debug('wakeup-storage', 'Saved wakeup config')\n}\n\n/**\n * Get or create default config\n * Includes migration logic to update existing configs to new default models\n */\nexport function getOrCreateConfig(): WakeupConfig {\n const existing = loadWakeupConfig()\n if (existing) {\n // Auto-migrate to new default models if selectedModels is empty\n // This ensures both Claude and Gemini families (both quota groups) are triggered\n if (!existing.selectedModels || existing.selectedModels.length === 0) {\n existing.selectedModels = ['claude-sonnet-4-5', 'gemini-3-flash', 'gemini-3-pro-low']\n saveWakeupConfig(existing)\n debug('wakeup-storage', 'Migrated config to new default models')\n }\n return existing\n }\n const defaultConfig = getDefaultConfig()\n saveWakeupConfig(defaultConfig)\n return defaultConfig\n}\n\n// ============================================================================\n// History Operations\n// ============================================================================\n\n/**\n * Load trigger history\n */\nexport function loadTriggerHistory(): TriggerRecord[] {\n return readJsonFile<TriggerRecord[]>(HISTORY_FILE_NAME, [])\n}\n\n/**\n * Save trigger history\n */\nexport function saveTriggerHistory(history: TriggerRecord[]): void {\n writeJsonFile(HISTORY_FILE_NAME, history)\n}\n\n/**\n * Add a trigger record to history (maintains ring buffer)\n */\nexport function addTriggerRecord(record: TriggerRecord): void {\n const history = loadTriggerHistory()\n \n // Add new record at the beginning\n history.unshift(record)\n \n // Trim to max entries\n if (history.length > MAX_HISTORY_ENTRIES) {\n history.splice(MAX_HISTORY_ENTRIES)\n }\n \n saveTriggerHistory(history)\n debug('wakeup-storage', `Added trigger record (total: ${history.length})`)\n}\n\n/**\n * Get recent trigger history\n */\nexport function getRecentHistory(limit: number = 10): TriggerRecord[] {\n const history = loadTriggerHistory()\n return history.slice(0, limit)\n}\n\n/**\n * Get last trigger record\n */\nexport function getLastTrigger(): TriggerRecord | null {\n const history = loadTriggerHistory()\n return history.length > 0 ? history[0] : null\n}\n\n/**\n * Clear trigger history\n */\nexport function clearTriggerHistory(): void {\n saveTriggerHistory([])\n debug('wakeup-storage', 'Cleared trigger history')\n}\n\n// ============================================================================\n// Reset State Operations\n// ============================================================================\n\n/**\n * Load reset deduplication state\n */\nexport function loadResetState(): ResetState {\n return readJsonFile<ResetState>(RESET_STATE_FILE_NAME, {})\n}\n\n/**\n * Save reset state\n */\nexport function saveResetState(state: ResetState): void {\n writeJsonFile(RESET_STATE_FILE_NAME, state)\n}\n\n/**\n * Update reset state for a specific model\n */\nexport function updateResetState(modelKey: string, resetAt: string): void {\n const state = loadResetState()\n \n state[modelKey] = {\n lastResetAt: resetAt,\n lastTriggeredTime: new Date().toISOString()\n }\n \n saveResetState(state)\n debug('wakeup-storage', `Updated reset state for ${modelKey}`)\n}\n\n/**\n * Get reset state for a specific model\n */\nexport function getModelResetState(modelKey: string): { lastResetAt: string; lastTriggeredTime: string } | null {\n const state = loadResetState()\n return state[modelKey] || null\n}\n\n/**\n * Clear reset state\n */\nexport function clearResetState(): void {\n saveResetState({})\n debug('wakeup-storage', 'Cleared reset state')\n}\n\n// ============================================================================\n// Model Mapping Operations\n// ============================================================================\n\n/**\n * Load model ID to constant mapping\n */\nexport function loadModelMapping(): ModelMapping {\n return readJsonFile<ModelMapping>(MODEL_MAPPING_FILE_NAME, {})\n}\n\n/**\n * Save model mapping\n */\nexport function saveModelMapping(mapping: ModelMapping): void {\n writeJsonFile(MODEL_MAPPING_FILE_NAME, mapping)\n debug('wakeup-storage', `Saved model mapping (${Object.keys(mapping).length} models)`)\n}\n\n/**\n * Update model mapping with new entries\n * Merges with existing mappings\n */\nexport function updateModelMapping(newMappings: ModelMapping): void {\n const existing = loadModelMapping()\n const merged = { ...existing, ...newMappings }\n saveModelMapping(merged)\n}\n\n/**\n * Get model constant for a model ID\n */\nexport function getModelConstant(modelId: string): string | undefined {\n const mapping = loadModelMapping()\n return mapping[modelId]\n}\n\n/**\n * Get reset key for a model (uses constant if available, else ID)\n */\nexport function getResetKey(modelId: string): string {\n return getModelConstant(modelId) || modelId\n}\n","/**\n * Account resolver for auto wake-up\n * Resolves which accounts to use for triggering based on config and availability\n */\n\nimport { debug } from '../core/logger.js'\nimport { getAccountManager } from '../accounts/manager.js'\n\n/**\n * Resolve which accounts to use for triggering\n * @param selectedAccounts Explicitly selected accounts from config (may be undefined)\n * @returns Array of valid account emails to use for triggering\n */\nexport function resolveAccounts(selectedAccounts?: string[]): string[] {\n const accountManager = getAccountManager()\n \n // Case 1: Explicit selection (even if empty array)\n if (selectedAccounts !== undefined) {\n debug('account-resolver', `Explicit account selection: ${selectedAccounts.length} accounts`)\n \n // Filter to only valid accounts\n const validAccounts = selectedAccounts.filter(email => {\n if (!accountManager.hasAccount(email)) {\n debug('account-resolver', `Account ${email} not found, skipping`)\n return false\n }\n \n const status = accountManager.getAccountStatus(email)\n if (status === 'invalid') {\n debug('account-resolver', `Account ${email} is invalid, skipping`)\n return false\n }\n \n // 'valid' or 'expired' (expired can be refreshed)\n return true\n })\n \n debug('account-resolver', `Resolved ${validAccounts.length} valid accounts from selection`)\n return validAccounts\n }\n \n // Case 2: No explicit selection - use fallback logic\n debug('account-resolver', 'No explicit selection, using fallback logic')\n \n // Prefer active account if valid\n const activeEmail = accountManager.getActiveEmail()\n if (activeEmail) {\n const status = accountManager.getAccountStatus(activeEmail)\n if (status === 'valid' || status === 'expired') {\n debug('account-resolver', `Using active account: ${activeEmail}`)\n return [activeEmail]\n }\n debug('account-resolver', `Active account ${activeEmail} is ${status}, trying fallback`)\n }\n \n // Fallback: use first available valid account\n const allEmails = accountManager.getAccountEmails()\n for (const email of allEmails) {\n const status = accountManager.getAccountStatus(email)\n if (status === 'valid' || status === 'expired') {\n debug('account-resolver', `Fallback to first valid account: ${email}`)\n return [email]\n }\n }\n \n // No valid accounts\n debug('account-resolver', 'No valid accounts found')\n return []\n}\n\n/**\n * Check if any accounts are available for triggering\n */\nexport function hasValidAccounts(selectedAccounts?: string[]): boolean {\n return resolveAccounts(selectedAccounts).length > 0\n}\n\n/**\n * Get a friendly description of account resolution state\n */\nexport function getAccountResolutionStatus(selectedAccounts?: string[]): string {\n const resolved = resolveAccounts(selectedAccounts)\n \n if (resolved.length === 0) {\n if (selectedAccounts !== undefined && selectedAccounts.length > 0) {\n return 'Selected accounts are invalid or not found'\n }\n return 'No valid accounts available'\n }\n \n if (resolved.length === 1) {\n return `Using account: ${resolved[0]}`\n }\n \n return `Using ${resolved.length} accounts: ${resolved.join(', ')}`\n}\n","/**\n * Schedule converter for auto wake-up\n * Converts schedule configuration to cron expressions\n */\n\nimport type { WakeupConfig, WeeklySchedule } from './types.js'\n\n/**\n * Convert wakeup config to cron expression\n * @param config Wake-up configuration\n * @returns Cron expression string (5 fields: minute hour day month weekday)\n */\nexport function configToCronExpression(config: WakeupConfig): string {\n // If custom cron expression provided, use it directly\n if (config.cronExpression) {\n return config.cronExpression\n }\n \n switch (config.scheduleMode) {\n case 'interval':\n return intervalToCron(config.intervalHours || 6)\n \n case 'daily':\n return dailyToCron(config.dailyTimes || ['09:00'])\n \n case 'weekly':\n return weeklyToCron(config.weeklySchedule || {})\n \n case 'custom':\n // Should have cronExpression set, fallback to every 6 hours\n return '0 */6 * * *'\n \n default:\n throw new Error(`Unknown schedule mode: ${config.scheduleMode}`)\n }\n}\n\n/**\n * Interval mode: every N hours\n * Example: every 6 hours produces cron \"0 STAR/6 * * *\" (STAR = asterisk)\n */\nfunction intervalToCron(hours: number): string {\n if (hours < 1 || hours > 23) {\n throw new Error('Interval hours must be between 1 and 23')\n }\n return `0 */${hours} * * *`\n}\n\n/**\n * Daily mode: at specific times each day\n * For multiple times, creates comma-separated hours\n * Example: [\"09:00\", \"18:00\"] produces cron \"0 9,18 * * *\"\n */\nfunction dailyToCron(times: string[]): string {\n if (times.length === 0) {\n throw new Error('Daily mode requires at least one time')\n }\n \n // Parse all times\n const parsedTimes = times.map(parseTime)\n \n // Group by minute (most common case: all same minute, usually :00)\n // For simplicity, use the first time's minute and all hours\n const [firstHour, firstMinute] = parsedTimes[0]\n const hours = parsedTimes.map(([h]) => h)\n \n // If all times have the same minute, use comma-separated hours\n const allSameMinute = parsedTimes.every(([, m]) => m === firstMinute)\n \n if (allSameMinute) {\n return `${firstMinute} ${hours.join(',')} * * *`\n }\n \n // Different minutes - just use the first time\n // (Multiple cron entries would require multiple install calls)\n return `${firstMinute} ${firstHour} * * *`\n}\n\n/**\n * Weekly mode: specific days at specific times\n * Example: day 1 at 09:00 and day 5 at 17:00 produces cron \"0 9 * * 1\"\n * Note: For multiple days with same time, uses comma-separated days\n */\nfunction weeklyToCron(schedule: WeeklySchedule): string {\n const days = Object.keys(schedule).map(Number).sort()\n \n if (days.length === 0) {\n throw new Error('Weekly mode requires at least one day')\n }\n \n // Use first day's first time\n const firstDay = days[0]\n const firstDayTimes = schedule[firstDay]\n \n if (!firstDayTimes || firstDayTimes.length === 0) {\n throw new Error(`No times specified for day ${firstDay}`)\n }\n \n const [hour, minute] = parseTime(firstDayTimes[0])\n \n // Create day list\n const daysStr = days.join(',')\n \n return `${minute} ${hour} * * ${daysStr}`\n}\n\n/**\n * Parse time string \"HH:MM\" to [hour, minute]\n */\nfunction parseTime(timeStr: string): [number, number] {\n const match = timeStr.match(/^(\\d{1,2}):(\\d{2})$/)\n if (!match) {\n throw new Error(`Invalid time format: ${timeStr}. Expected HH:MM`)\n }\n \n const hour = parseInt(match[1], 10)\n const minute = parseInt(match[2], 10)\n \n if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {\n throw new Error(`Invalid time values: ${timeStr}`)\n }\n \n return [hour, minute]\n}\n\n/**\n * Validate a cron expression (basic validation)\n * @param expr Cron expression to validate\n * @returns true if valid, false otherwise\n */\nexport function validateCronExpression(expr: string): boolean {\n // Basic validation: 5 fields (minute hour day month weekday)\n const parts = expr.trim().split(/\\s+/)\n if (parts.length !== 5) {\n return false\n }\n \n // Each field should match basic cron syntax\n const fieldPattern = /^(\\*|[\\d,\\-\\/\\*]+)$/\n return parts.every(part => fieldPattern.test(part))\n}\n\n/**\n * Get human-readable description of schedule\n */\nexport function getScheduleDescription(config: WakeupConfig): string {\n if (!config.enabled) {\n return 'Disabled'\n }\n \n if (config.wakeOnReset) {\n const cooldown = config.resetCooldownMinutes || 10\n return `Quota-reset based (${cooldown}min cooldown)`\n }\n \n switch (config.scheduleMode) {\n case 'interval':\n const hours = config.intervalHours || 6\n return `Every ${hours} hour${hours > 1 ? 's' : ''}`\n \n case 'daily':\n const times = config.dailyTimes || ['09:00']\n if (times.length === 1) {\n return `Daily at ${times[0]}`\n }\n return `Daily at ${times.join(', ')}`\n \n case 'weekly':\n const days = Object.keys(config.weeklySchedule || {}).map(Number)\n const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']\n const dayList = days.map(d => dayNames[d]).join(', ')\n return `Weekly on ${dayList}`\n \n case 'custom':\n return `Custom: ${config.cronExpression || 'Not set'}`\n \n default:\n return 'Unknown schedule'\n }\n}\n\n/**\n * Calculate next run time from cron expression (simplified)\n * Returns a human-readable estimate\n */\nexport function getNextRunEstimate(cronExpression: string): string {\n try {\n const parts = cronExpression.trim().split(/\\s+/)\n if (parts.length !== 5) {\n return 'Invalid cron'\n }\n \n const [minute, hour, day, month, weekday] = parts\n \n // Simple cases\n if (hour.startsWith('*/')) {\n const interval = parseInt(hour.substring(2), 10)\n return `Every ${interval} hour${interval > 1 ? 's' : ''}`\n }\n \n if (day === '*' && month === '*' && weekday === '*') {\n // Daily - show specific time\n const displayHour = hour.includes(',') ? hour.split(',')[0] : hour\n return `Daily at ${displayHour.padStart(2, '0')}:${minute.padStart(2, '0')}`\n }\n \n if (weekday !== '*') {\n const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']\n const dayNums = weekday.split(',').map(Number)\n const dayList = dayNums.map(d => dayNames[d] || d).join(', ')\n return `${dayList} at ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`\n }\n \n return cronExpression\n } catch {\n return cronExpression\n }\n}\n","/**\n * Cron installer for auto wake-up\n * Manages cron job installation for macOS/Linux\n */\n\nimport { execSync, exec } from 'child_process'\nimport { promisify } from 'util'\nimport { debug } from '../core/logger.js'\nimport type { CronInstallResult, CronStatus } from './types.js'\n\nconst execAsync = promisify(exec)\n\n// Comment marker to identify our cron entries\nconst CRON_COMMENT_MARKER = 'antigravity-usage-wakeup'\n\n/**\n * Get PATH directories for cron environment\n * Returns directories where node and npm binaries are found\n * This makes cron jobs portable across different machines and Node.js installations\n */\nfunction getBinDirectories(): string[] {\n const dirs = new Set<string>()\n \n try {\n // Get node's bin directory from current process\n const nodePath = process.execPath\n const nodeDir = nodePath.substring(0, nodePath.lastIndexOf('/'))\n if (nodeDir) {\n dirs.add(nodeDir)\n debug('cron-installer', `Found node bin dir: ${nodeDir}`)\n }\n } catch {\n debug('cron-installer', 'Could not determine node bin directory')\n }\n \n try {\n // Get npm global bin directory\n const npmBin = execSync('npm bin -g', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe']\n }).trim()\n if (npmBin) {\n dirs.add(npmBin)\n debug('cron-installer', `Found npm bin dir: ${npmBin}`)\n }\n } catch {\n debug('cron-installer', 'Could not determine npm bin directory')\n }\n \n // Try to get user's current PATH as fallback\n // This helps capture paths from nvm, homebrew, etc.\n if (process.env.PATH) {\n const userPaths = process.env.PATH.split(':').filter(p => {\n // Include paths that might contain node or npm binaries\n return p.includes('node') || p.includes('npm') || \n p.includes('nvm') || p.includes('.local') ||\n p === '/usr/local/bin' || p === '/opt/homebrew/bin'\n })\n userPaths.forEach(p => {\n if (p) {\n dirs.add(p)\n debug('cron-installer', `Added user PATH: ${p}`)\n }\n })\n }\n \n // Add standard system paths (always include these)\n dirs.add('/usr/local/bin')\n dirs.add('/usr/bin')\n dirs.add('/bin')\n dirs.add('/opt/homebrew/bin') // For Apple Silicon Macs\n \n return Array.from(dirs)\n}\n\n/**\n * Load current crontab entries\n */\nasync function loadCrontab(): Promise<string[]> {\n try {\n const { stdout } = await execAsync('crontab -l 2>/dev/null || echo \"\"')\n const lines = stdout.split('\\n').filter(line => line.trim())\n debug('cron-installer', `Loaded ${lines.length} crontab entries`)\n return lines\n } catch {\n debug('cron-installer', 'No existing crontab or error loading')\n return []\n }\n}\n\n/**\n * Save crontab entries\n */\nasync function saveCrontab(lines: string[]): Promise<void> {\n const content = lines.join('\\n') + '\\n'\n \n try {\n // Write to temp file and load into crontab\n const { exec: execCallback } = await import('child_process')\n \n await new Promise<void>((resolve, reject) => {\n const proc = execCallback('crontab -', (err) => {\n if (err) reject(err)\n else resolve()\n })\n proc.stdin?.write(content)\n proc.stdin?.end()\n })\n \n debug('cron-installer', 'Saved crontab successfully')\n } catch (err) {\n debug('cron-installer', 'Error saving crontab:', err)\n throw err\n }\n}\n\n/**\n * Remove all antigravity-usage-wakeup entries from crontab lines\n */\nfunction removeWakeupEntries(lines: string[]): string[] {\n return lines.filter(line => !line.includes(CRON_COMMENT_MARKER))\n}\n\n/**\n * Check if running on a supported platform\n */\nexport function isCronSupported(): boolean {\n return process.platform === 'darwin' || process.platform === 'linux'\n}\n\n/**\n * Install cron job for scheduled wake-up\n * @param cronExpression Cron expression (5 fields: minute hour day month weekday)\n * @returns Installation result with success status or manual instructions\n */\nexport async function installCronJob(cronExpression: string): Promise<CronInstallResult> {\n if (!isCronSupported()) {\n return {\n success: false,\n error: `Cron is not supported on ${process.platform}. Windows Task Scheduler support coming soon.`,\n manualInstructions: getWindowsInstructions(cronExpression)\n }\n }\n \n try {\n // Get PATH directories - auto-detected from current environment\n // This makes the cron job portable across different machines and Node.js installations\n const binDirs = getBinDirectories()\n const pathValue = binDirs.join(':')\n \n // Load existing crontab\n const lines = await loadCrontab()\n \n // Remove any existing antigravity-usage entries (both PATH and job lines)\n const filteredLines = removeWakeupEntries(lines)\n \n // Add PATH if not already set for other cron jobs\n const hasPath = filteredLines.some(line => line.startsWith('PATH='))\n if (!hasPath) {\n filteredLines.unshift(`PATH=${pathValue}`)\n }\n \n // Create new cron entry with simple, portable command\n // Using 'antigravity-usage' instead of absolute paths makes it work anywhere\n const cronLine = `${cronExpression} antigravity-usage wakeup trigger --scheduled # ${CRON_COMMENT_MARKER}`\n \n // Add new entry\n filteredLines.push(cronLine)\n \n // Save crontab\n await saveCrontab(filteredLines)\n \n debug('cron-installer', `Installed cron job: ${cronLine}`)\n debug('cron-installer', `Using PATH: ${pathValue}`)\n \n return {\n success: true,\n cronExpression\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err)\n debug('cron-installer', `Failed to install cron job: ${errorMessage}`)\n \n return {\n success: false,\n error: errorMessage,\n manualInstructions: getManualInstructions(cronExpression)\n }\n }\n}\n\n/**\n * Uninstall cron job\n * @returns true if successful, false otherwise\n */\nexport async function uninstallCronJob(): Promise<boolean> {\n if (!isCronSupported()) {\n debug('cron-installer', 'Cron not supported on this platform')\n return false\n }\n \n try {\n // Load existing crontab\n const lines = await loadCrontab()\n \n // Remove our entries\n const filteredLines = removeWakeupEntries(lines)\n \n // If nothing changed, already uninstalled\n if (filteredLines.length === lines.length) {\n debug('cron-installer', 'No cron job found to uninstall')\n return true\n }\n \n // Save updated crontab\n await saveCrontab(filteredLines)\n \n debug('cron-installer', 'Uninstalled cron job successfully')\n return true\n } catch (err) {\n debug('cron-installer', 'Failed to uninstall cron job:', err)\n return false\n }\n}\n\n/**\n * Check if cron job is installed\n */\nexport async function isCronJobInstalled(): Promise<boolean> {\n if (!isCronSupported()) {\n return false\n }\n \n try {\n const lines = await loadCrontab()\n return lines.some(line => line.includes(CRON_COMMENT_MARKER))\n } catch {\n return false\n }\n}\n\n/**\n * Get current cron job status\n */\nexport async function getCronStatus(): Promise<CronStatus> {\n if (!isCronSupported()) {\n return { installed: false }\n }\n \n try {\n const lines = await loadCrontab()\n const cronLine = lines.find(line => line.includes(CRON_COMMENT_MARKER))\n \n if (!cronLine) {\n return { installed: false }\n }\n \n // Extract cron expression from line\n const parts = cronLine.trim().split(/\\s+/)\n const cronExpression = parts.slice(0, 5).join(' ')\n \n return {\n installed: true,\n cronExpression,\n nextRun: getNextRunDescription(cronExpression)\n }\n } catch {\n return { installed: false }\n }\n}\n\n/**\n * Generate manual instructions for cron setup\n */\nfunction getManualInstructions(cronExpression: string): string {\n const binDirs = getBinDirectories()\n const pathValue = binDirs.join(':')\n \n return `\nFailed to automatically install cron job. Please add manually:\n\n1. Open terminal and run: crontab -e\n\n2. Add these lines:\n PATH=${pathValue}\n ${cronExpression} antigravity-usage wakeup trigger --scheduled # ${CRON_COMMENT_MARKER}\n\n3. Save and exit the editor\n\nTo verify, run: crontab -l\n`.trim()\n}\n\n/**\n * Generate instructions for Windows users\n */\nfunction getWindowsInstructions(cronExpression: string): string {\n return `\nWindows Task Scheduler support is not yet available.\n\nTo set up manually using Task Scheduler:\n\n1. Open Task Scheduler (taskschd.msc)\n2. Create a new Basic Task\n3. Set trigger: Based on your schedule (${cronExpression})\n4. Set action: Start a program\n - Program: antigravity-usage\n - Arguments: wakeup trigger --scheduled\n5. Save the task\n\nAlternatively, use Windows Subsystem for Linux (WSL) with cron.\n`.trim()\n}\n\n/**\n * Get human-readable description of next run\n */\nfunction getNextRunDescription(cronExpression: string): string {\n try {\n const parts = cronExpression.split(/\\s+/)\n if (parts.length !== 5) return 'Unknown'\n \n const [minute, hour] = parts\n \n // Interval-based\n if (hour.startsWith('*/')) {\n const hours = parseInt(hour.substring(2), 10)\n const now = new Date()\n const currentHour = now.getHours()\n const nextHour = Math.ceil((currentHour + 1) / hours) * hours\n const isToday = nextHour < 24\n return isToday ? `Today around ${nextHour}:00` : 'Tomorrow'\n }\n \n // Specific time\n const hourNum = parseInt(hour.split(',')[0], 10)\n const minuteNum = parseInt(minute, 10)\n const now = new Date()\n const currentMinutes = now.getHours() * 60 + now.getMinutes()\n const targetMinutes = hourNum * 60 + minuteNum\n \n if (targetMinutes > currentMinutes) {\n return `Today at ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`\n }\n return `Tomorrow at ${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`\n } catch {\n return 'Unknown'\n }\n}\n","/**\n * Trigger service for auto wake-up\n * Executes actual AI requests to warm up models\n */\n\nimport { debug } from '../core/logger.js'\nimport { getTokenManagerForAccount } from '../google/token-manager.js'\nimport { CloudCodeClient } from '../google/cloudcode.js'\nimport { addTriggerRecord } from './storage.js'\nimport type { \n TriggerOptions, \n TriggerResult, \n ModelTriggerResult,\n TriggerRecord,\n TokenUsage\n} from './types.js'\n\n// Constants\nconst DEFAULT_PROMPT = 'hi'\nconst REQUEST_TIMEOUT_MS = 30000 // 30 seconds\nconst MAX_CONCURRENT_REQUESTS = 4\n\n/**\n * Execute trigger for specified models and account\n * @param options Trigger options including models, account, and prompt\n * @returns Trigger result with success status and per-model results\n */\nexport async function executeTrigger(options: TriggerOptions): Promise<TriggerResult> {\n const { \n models, \n accountEmail, \n triggerType, \n triggerSource, \n customPrompt,\n maxOutputTokens \n } = options\n \n debug('trigger-service', `Executing trigger for ${models.length} models with account ${accountEmail}`)\n \n if (models.length === 0) {\n debug('trigger-service', 'No models to trigger')\n return { success: true, results: [] }\n }\n \n // Get or create token manager for this account\n let tokenManager\n try {\n tokenManager = getTokenManagerForAccount(accountEmail)\n } catch (err) {\n debug('trigger-service', `Failed to get token manager for ${accountEmail}:`, err)\n \n // Record failure for all models\n const results: ModelTriggerResult[] = models.map(modelId => ({\n modelId,\n success: false,\n durationMs: 0,\n error: `Failed to get credentials for ${accountEmail}`\n }))\n \n recordResults(results, options)\n return { success: false, results }\n }\n \n // Ensure we have valid tokens (trigger refresh if needed)\n try {\n await tokenManager.getValidAccessToken()\n } catch (err) {\n // Extract detailed error message for better diagnostics\n let errorMessage = `Authentication failed for ${accountEmail}`\n \n if (err && typeof err === 'object' && 'getDetailedMessage' in err) {\n // TokenRefreshError with detailed message\n errorMessage = (err as { getDetailedMessage: () => string }).getDetailedMessage()\n } else if (err instanceof Error) {\n errorMessage = `Token refresh failed: ${err.message}`\n }\n \n debug('trigger-service', `Failed to refresh token for ${accountEmail}:`, err)\n \n const results: ModelTriggerResult[] = models.map(modelId => ({\n modelId,\n success: false,\n durationMs: 0,\n error: errorMessage\n }))\n \n recordResults(results, options)\n return { success: false, results }\n }\n \n // Create CloudCode client\n const client = new CloudCodeClient(tokenManager)\n \n // Debug: check if projectId was loaded from cache\n debug('trigger-service', `Account ${accountEmail} projectId from tokenManager: ${tokenManager.getProjectId()}`)\n \n // Resolve project ID (may require onboarding if first time)\n try {\n const projectId = await client.resolveProjectId()\n if (projectId) {\n debug('trigger-service', `Project ID resolved: ${projectId}`)\n // Save for future use\n tokenManager.setProjectId(projectId)\n } else {\n debug('trigger-service', 'WARNING: Could not resolve project ID')\n }\n } catch (err) {\n debug('trigger-service', 'Failed to resolve project ID:', err)\n }\n \n // Prepare prompt\n const userPrompt = customPrompt || DEFAULT_PROMPT\n \n // Trigger models with concurrency limit\n const results: ModelTriggerResult[] = []\n \n // Process in batches of MAX_CONCURRENT_REQUESTS\n for (let i = 0; i < models.length; i += MAX_CONCURRENT_REQUESTS) {\n const batch = models.slice(i, i + MAX_CONCURRENT_REQUESTS)\n \n debug('trigger-service', `Processing batch ${i / MAX_CONCURRENT_REQUESTS + 1}: ${batch.join(', ')}`)\n \n const batchResults = await Promise.all(\n batch.map(modelId => triggerSingleModel(client, modelId, userPrompt, maxOutputTokens))\n )\n \n results.push(...batchResults)\n }\n \n // Record results in history\n recordResults(results, options)\n \n const allSuccess = results.every(r => r.success)\n const successCount = results.filter(r => r.success).length\n \n debug('trigger-service', `Trigger complete: ${successCount}/${results.length} succeeded`)\n \n return { success: allSuccess, results }\n}\n\n/**\n * Trigger a single model\n */\nasync function triggerSingleModel(\n client: CloudCodeClient,\n modelId: string,\n prompt: string,\n maxTokens?: number\n): Promise<ModelTriggerResult> {\n const startTime = Date.now()\n \n debug('trigger-service', `Triggering model: ${modelId}`)\n \n try {\n // Create timeout promise\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error('Request timed out')), REQUEST_TIMEOUT_MS)\n })\n \n // Race between actual request and timeout\n const response = await Promise.race([\n client.generateContent(modelId, prompt, maxTokens),\n timeoutPromise\n ])\n \n const durationMs = Date.now() - startTime\n \n debug('trigger-service', `Model ${modelId} responded in ${durationMs}ms`)\n \n return {\n modelId,\n success: true,\n durationMs,\n response: response.text.substring(0, 500), // Truncate to 500 chars\n tokensUsed: response.tokensUsed\n }\n } catch (err) {\n const durationMs = Date.now() - startTime\n const errorMessage = err instanceof Error ? err.message : String(err)\n \n debug('trigger-service', `Model ${modelId} failed after ${durationMs}ms: ${errorMessage}`)\n \n return {\n modelId,\n success: false,\n durationMs,\n error: errorMessage\n }\n }\n}\n\n/**\n * Record trigger results in history\n */\nfunction recordResults(results: ModelTriggerResult[], options: TriggerOptions): void {\n const { triggerType, triggerSource, accountEmail, customPrompt } = options\n const prompt = customPrompt || DEFAULT_PROMPT\n \n // Create a record for each model result\n for (const result of results) {\n const record: TriggerRecord = {\n timestamp: new Date().toISOString(),\n success: result.success,\n triggerType,\n triggerSource,\n models: [result.modelId],\n accountEmail,\n durationMs: result.durationMs,\n prompt,\n response: result.response,\n error: result.error,\n tokensUsed: result.tokensUsed\n }\n \n addTriggerRecord(record)\n }\n}\n\n/**\n * Execute a quick test trigger (for manual testing)\n * @param modelId Model to test\n * @param accountEmail Account to use\n * @param prompt Optional custom prompt\n */\nexport async function testTrigger(\n modelId: string,\n accountEmail: string,\n prompt?: string\n): Promise<ModelTriggerResult> {\n const result = await executeTrigger({\n models: [modelId],\n accountEmail,\n triggerType: 'manual',\n triggerSource: 'manual',\n customPrompt: prompt\n })\n \n return result.results[0] || {\n modelId,\n success: false,\n durationMs: 0,\n error: 'No result returned'\n }\n}\n","/**\n * Reset detector for auto wake-up\n * \n * Smart trigger logic:\n * - Triggers ALL available models from quota snapshot\n * - Triggers for ALL valid accounts\n * - Only triggers when model is \"unused\": 100% remaining AND ~5h until reset\n */\n\nimport { debug } from '../core/logger.js'\nimport type { QuotaSnapshot, ModelQuotaInfo } from '../quota/types.js'\nimport { \n loadWakeupConfig, \n loadResetState, \n updateResetState\n} from './storage.js'\nimport { getAccountManager } from '../accounts/manager.js'\nimport { executeTrigger } from './trigger-service.js'\nimport type { DetectionResult } from './types.js'\n\n// Smart trigger thresholds\nconst FULL_QUOTA_THRESHOLD = 99 // Consider \"full\" if >= 99%\nconst RESET_TIME_MIN_HOURS = 4.5 // At least 4.5 hours until reset\nconst RESET_TIME_MAX_HOURS = 5.5 // At most 5.5 hours until reset (catches the ~5h window)\nconst RESET_TIME_MIN_MS = RESET_TIME_MIN_HOURS * 60 * 60 * 1000\nconst RESET_TIME_MAX_MS = RESET_TIME_MAX_HOURS * 60 * 60 * 1000\n\n// Cooldown between triggers for same model\nconst DEFAULT_COOLDOWN_MS = 60 * 60 * 1000 // 1 hour (since we're looking at ~5h window)\n\n/**\n * Check if a model is \"unused\" and should be triggered\n * \n * Unused = 100% quota remaining AND reset time is approximately 5 hours\n * (meaning the model hasn't been used this quota cycle)\n */\nexport function isModelUnused(model: ModelQuotaInfo): boolean {\n // Must have remaining percentage data\n if (model.remainingPercentage === undefined) {\n debug('reset-detector', `${model.modelId}: No remaining percentage data`)\n return false\n }\n \n // Check if quota is full (100% or very close)\n if (model.remainingPercentage < FULL_QUOTA_THRESHOLD) {\n debug('reset-detector', `${model.modelId}: Not full (${model.remainingPercentage}%)`)\n return false\n }\n \n // Must have time until reset data\n if (model.timeUntilResetMs === undefined) {\n debug('reset-detector', `${model.modelId}: No reset time data`)\n return false\n }\n \n // Check if reset time is in the ~5h window (4.5h to 5.5h)\n // This means it just reset and hasn't been used\n if (model.timeUntilResetMs < RESET_TIME_MIN_MS || model.timeUntilResetMs > RESET_TIME_MAX_MS) {\n const hoursUntilReset = (model.timeUntilResetMs / (60 * 60 * 1000)).toFixed(1)\n debug('reset-detector', `${model.modelId}: Reset time ${hoursUntilReset}h not in 4.5-5.5h window`)\n return false\n }\n \n debug('reset-detector', `${model.modelId}: UNUSED - 100% remaining, ~5h until reset`)\n return true\n}\n\n/**\n * Get all valid account emails\n */\nfunction getAllValidAccounts(): string[] {\n const accountManager = getAccountManager()\n const allEmails = accountManager.getAccountEmails()\n \n return allEmails.filter(email => {\n const status = accountManager.getAccountStatus(email)\n return status === 'valid' || status === 'expired' // Expired can be refreshed\n })\n}\n\n/**\n * Detect unused models and trigger wake-up for all accounts\n * \n * New smart logic:\n * 1. Check ALL models in the quota snapshot\n * 2. Find models that are \"unused\" (100% + ~5h reset)\n * 3. Trigger for ALL valid accounts\n */\nexport async function detectResetAndTrigger(snapshot: QuotaSnapshot): Promise<DetectionResult> {\n debug('reset-detector', 'Checking for unused models (smart trigger)')\n \n // Load config\n const config = loadWakeupConfig()\n \n // Must be enabled\n if (!config || !config.enabled) {\n debug('reset-detector', 'Wakeup is not enabled')\n return { triggered: false, triggeredModels: [] }\n }\n \n // Get ALL valid accounts\n const accounts = getAllValidAccounts()\n if (accounts.length === 0) {\n debug('reset-detector', 'No valid accounts available')\n return { triggered: false, triggeredModels: [] }\n }\n \n debug('reset-detector', `Found ${accounts.length} valid accounts`)\n \n // Load reset state for cooldown\n const resetState = loadResetState()\n const now = Date.now()\n \n // Find ALL unused models (check every model in snapshot)\n const modelsToTrigger: string[] = []\n \n for (const model of snapshot.models) {\n // Check if model is unused\n if (!isModelUnused(model)) {\n continue\n }\n \n // Check cooldown (don't trigger same model too frequently)\n const previousState = resetState[model.modelId]\n if (previousState) {\n const lastTriggered = new Date(previousState.lastTriggeredTime).getTime()\n const cooldownRemaining = DEFAULT_COOLDOWN_MS - (now - lastTriggered)\n if (cooldownRemaining > 0) {\n debug('reset-detector', `${model.modelId}: In cooldown (${Math.round(cooldownRemaining / 60000)}min remaining)`)\n continue\n }\n }\n \n modelsToTrigger.push(model.modelId)\n \n // Update state to prevent re-triggering\n updateResetState(model.modelId, model.resetTime || new Date().toISOString())\n }\n \n if (modelsToTrigger.length === 0) {\n debug('reset-detector', 'No unused models to trigger')\n return { triggered: false, triggeredModels: [] }\n }\n \n console.log(`\\n🔄 Found ${modelsToTrigger.length} unused model(s): ${modelsToTrigger.join(', ')}`)\n console.log(` Triggering for ${accounts.length} account(s)...`)\n \n // Trigger for ALL accounts\n let successCount = 0\n for (const accountEmail of accounts) {\n try {\n const result = await executeTrigger({\n models: modelsToTrigger,\n accountEmail,\n triggerType: 'auto',\n triggerSource: 'quota_reset',\n customPrompt: config.customPrompt,\n maxOutputTokens: config.maxOutputTokens\n })\n \n const modelSuccess = result.results.filter(r => r.success).length\n console.log(` ✅ ${accountEmail}: ${modelSuccess}/${modelsToTrigger.length} succeeded`)\n if (modelSuccess > 0) successCount++\n } catch (err) {\n console.log(` ❌ ${accountEmail}: ${err instanceof Error ? err.message : err}`)\n debug('reset-detector', `Trigger failed for ${accountEmail}:`, err)\n }\n }\n \n console.log(`\\n📊 Wake-up complete: ${successCount}/${accounts.length} accounts triggered\\n`)\n \n return { \n triggered: true, \n triggeredModels: modelsToTrigger \n }\n}\n\n/**\n * Get list of unused models for display/testing\n */\nexport function findUnusedModels(snapshot: QuotaSnapshot): ModelQuotaInfo[] {\n return snapshot.models.filter(isModelUnused)\n}\n\n/**\n * Check if any models need triggering (for status display)\n */\nexport function hasUnusedModels(snapshot: QuotaSnapshot): boolean {\n return snapshot.models.some(isModelUnused)\n}\n"],"mappings":"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","names":["URL","readFileSync","join","join","join","readFileSync","existsSync","readFileSync","writeFileSync","mkdirSync","dirname","existsSync","readFileSync","dirname","mkdirSync","writeFileSync","error","URL","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","dirname","existsSync","mkdirSync","writeFileSync","readFileSync","existsSync","EXPIRY_BUFFER_MS","removed","sleep","platform","exec","promisify","execAsync","promisify","exec","platform","https","http","https","http","parsePromptCredits","Table","Table","info","inquirer","Table","join","readFileSync","writeFileSync","existsSync","mkdirSync","join","existsSync","mkdirSync","readFileSync","writeFileSync","exec","promisify","execAsync","promisify","exec","now","results","inquirer","success","Table"]}
|