when-does-my-quota-refresh 1.0.1 → 1.2.0
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/dist/accounts-FH6AKZT7.js +27 -0
- package/dist/{auth-K5ETZYGY.js → auth-GX4ZIG5O.js} +2 -2
- package/dist/auth-GX4ZIG5O.js.map +1 -0
- package/dist/chunk-H7BEO7IF.js +2 -0
- package/dist/chunk-H7BEO7IF.js.map +1 -0
- package/dist/{chunk-24ILGZJ2.js → chunk-VLP22VAR.js} +263 -175
- package/dist/chunk-VLP22VAR.js.map +1 -0
- package/dist/cli/index.js +219 -29
- package/dist/cli/index.js.map +1 -1
- package/dist/sdk/index.d.ts +16 -5
- package/dist/sdk/index.js +409 -182
- package/dist/sdk/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-24ILGZJ2.js.map +0 -1
- /package/dist/{auth-K5ETZYGY.js.map → accounts-FH6AKZT7.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sources/oauth/client.ts","../src/core/logger.ts","../src/sources/cloud-code-api.ts","../src/sdk/accounts/storage.ts","../src/core/config.ts","../src/core/errors.ts","../src/sdk/accounts/auth.ts"],"sourcesContent":["/**\n * Google OAuth client for Cloud Code API\n *\n * Handles the OAuth2 flow for remote quota fetching.\n */\n\nimport https from 'https'\nimport { URL } from 'url'\nimport { debug } from '../../core/logger.js'\nimport type { OAuthTokenResponse, StoredTokens } from '../../sdk/types.js'\nimport {\n CLOUD_CODE_ENDPOINTS,\n CLOUD_CODE_DEFAULT_BODY,\n OAUTH_CLIENT_ID,\n OAUTH_CLIENT_SECRET,\n OAUTH_SCOPES,\n OAUTH_REDIRECT_URI,\n} from '../cloud-code-api.js'\nimport { saveAccountTokens } from '../../sdk/accounts/storage.js'\n\nexport class OAuthClient {\n private tokens: StoredTokens | null = null\n\n constructor(tokens?: StoredTokens) {\n this.tokens = tokens || null\n }\n\n /**\n * Generate the OAuth authorization URL for user login\n */\n getAuthUrl(redirectUri?: string): string {\n const params = new URLSearchParams({\n client_id: OAUTH_CLIENT_ID,\n redirect_uri: redirectUri || OAUTH_REDIRECT_URI,\n response_type: 'code',\n scope: OAUTH_SCOPES,\n access_type: 'offline',\n prompt: 'consent',\n })\n return `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`\n }\n\n /**\n * Exchange an authorization code for tokens\n */\n async exchangeCode(code: string, redirectUri?: string): Promise<StoredTokens> {\n const body = new URLSearchParams({\n code,\n client_id: OAUTH_CLIENT_ID,\n client_secret: OAUTH_CLIENT_SECRET,\n redirect_uri: redirectUri || OAUTH_REDIRECT_URI,\n grant_type: 'authorization_code',\n })\n\n const response = await this.postUrlEncoded('https://oauth2.googleapis.com/token', body)\n const data = response as OAuthTokenResponse\n\n this.tokens = {\n accessToken: data.access_token,\n refreshToken: data.refresh_token || '',\n expiresAt: Date.now() + data.expires_in * 1000,\n }\n\n return this.tokens\n }\n\n /**\n * Refresh the access token\n */\n async refreshAccessToken(): Promise<StoredTokens> {\n if (!this.tokens?.refreshToken) {\n throw new Error('No refresh token available')\n }\n\n const body = new URLSearchParams({\n client_id: OAUTH_CLIENT_ID,\n client_secret: OAUTH_CLIENT_SECRET,\n refresh_token: this.tokens.refreshToken,\n grant_type: 'refresh_token',\n })\n\n const response = await this.postUrlEncoded('https://oauth2.googleapis.com/token', body)\n const data = response as OAuthTokenResponse\n\n this.tokens = {\n ...this.tokens,\n accessToken: data.access_token,\n expiresAt: Date.now() + data.expires_in * 1000,\n }\n\n // Persist refreshed token to disk so it survives restarts\n if (this.tokens.email) {\n try {\n saveAccountTokens(this.tokens.email, this.tokens)\n debug('oauth', `Persisted refreshed token for ${this.tokens.email}`)\n } catch (err) {\n debug('oauth', `Failed to persist refreshed token: ${err}`)\n }\n }\n\n return this.tokens\n }\n\n /**\n * Get a valid access token, refreshing if necessary\n */\n async getAccessToken(): Promise<string> {\n if (!this.tokens) throw new Error('Not authenticated')\n if (Date.now() >= this.tokens.expiresAt - 60000) {\n await this.refreshAccessToken()\n }\n return this.tokens.accessToken!\n }\n\n /**\n * Get stored tokens\n */\n getTokens(): StoredTokens | null {\n return this.tokens\n }\n\n /**\n * Make an authenticated POST request to the Cloud Code API\n */\n async fetchQuotaSummary(): Promise<unknown> {\n const token = await this.getAccessToken()\n return this.authenticatedPost(\n CLOUD_CODE_ENDPOINTS.retrieveUserQuotaSummary,\n CLOUD_CODE_DEFAULT_BODY,\n token\n )\n }\n\n async fetchUserStatus(): Promise<unknown> {\n const token = await this.getAccessToken()\n return this.authenticatedPost(\n CLOUD_CODE_ENDPOINTS.loadCodeAssist,\n CLOUD_CODE_DEFAULT_BODY,\n token\n )\n }\n\n async fetchAvailableModels(): Promise<unknown> {\n const token = await this.getAccessToken()\n return this.authenticatedPost(\n CLOUD_CODE_ENDPOINTS.fetchAvailableModels,\n CLOUD_CODE_DEFAULT_BODY,\n token\n )\n }\n\n /**\n * Fetch the authenticated user's profile (email, name, etc.)\n */\n async fetchUserInfo(): Promise<{ email?: string; name?: string }> {\n const token = await this.getAccessToken()\n return new Promise((resolve, reject) => {\n const options: https.RequestOptions = {\n hostname: 'www.googleapis.com',\n path: '/oauth2/v3/userinfo',\n method: 'GET',\n headers: {\n 'Authorization': `Bearer ${token}`,\n },\n timeout: 10000,\n }\n\n const req = https.request(options, (res) => {\n let data = ''\n res.on('data', (chunk: Buffer) => { data += chunk })\n res.on('end', () => {\n try {\n const info = JSON.parse(data)\n resolve({ email: info.email, name: info.name })\n } catch {\n resolve({})\n }\n })\n })\n req.on('error', () => resolve({}))\n req.on('timeout', () => { req.destroy(); resolve({}) })\n req.end()\n })\n }\n\n // ── HTTP Helpers ────────────────────────────────────────────────\n\n private authenticatedPost(url: string, body: unknown, token: string): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const parsed = new URL(url)\n const data = JSON.stringify(body)\n const options: https.RequestOptions = {\n hostname: parsed.hostname,\n path: parsed.pathname,\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`,\n 'Content-Length': Buffer.byteLength(data),\n },\n timeout: 10000,\n }\n\n const req = https.request(options, (res) => {\n let responseData = ''\n res.on('data', (chunk: Buffer) => { responseData += chunk })\n res.on('end', () => {\n if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) {\n reject(new Error(`HTTP ${res.statusCode}: ${responseData.slice(0, 200)}`))\n return\n }\n try {\n resolve(JSON.parse(responseData))\n } catch {\n reject(new Error(`Invalid JSON: ${responseData.slice(0, 200)}`))\n }\n })\n })\n req.on('error', reject)\n req.on('timeout', () => { req.destroy(); reject(new Error('Timeout')) })\n req.write(data)\n req.end()\n })\n }\n\n private postUrlEncoded(url: string, body: URLSearchParams): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const parsed = new URL(url)\n const data = body.toString()\n const options: https.RequestOptions = {\n hostname: parsed.hostname,\n path: parsed.pathname,\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'Content-Length': Buffer.byteLength(data),\n },\n timeout: 10000,\n }\n\n const req = https.request(options, (res) => {\n let responseData = ''\n res.on('data', (chunk: Buffer) => { responseData += chunk })\n res.on('end', () => {\n if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) {\n reject(new Error(`HTTP ${res.statusCode}: ${responseData.slice(0, 200)}`))\n return\n }\n try {\n resolve(JSON.parse(responseData))\n } catch {\n reject(new Error(`Invalid JSON: ${responseData.slice(0, 200)}`))\n }\n })\n })\n req.on('error', reject)\n req.on('timeout', () => { req.destroy(); reject(new Error('Timeout')) })\n req.write(data)\n req.end()\n })\n }\n}\n","/**\n * Simple logger with debug flag\n */\n\nlet _verbose = false\n\nexport function setVerbose(verbose: boolean): void {\n _verbose = verbose\n}\n\nexport function debug(module: string, msg: string, data?: unknown): void {\n if (!_verbose) return\n const prefix = `[${module}]`\n if (data !== undefined) {\n console.error(`${prefix} ${msg}`, data)\n } else {\n console.error(`${prefix} ${msg}`)\n }\n}\n\nexport function info(msg: string): void {\n console.error(msg)\n}\n\nexport function warn(msg: string): void {\n console.error(`⚠ ${msg}`)\n}\n","/**\n * Google Cloud Code API endpoints for remote quota fetching\n *\n * Used as fallback when local sources are unavailable.\n * Requires OAuth authentication.\n */\n\nexport const CLOUD_CODE_ENDPOINTS = {\n /** Load code assist configuration */\n loadCodeAssist: 'https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist',\n\n /** Onboard a new user */\n onboardUser: 'https://cloudcode-pa.googleapis.com/v1internal:onboardUser',\n\n /** Fetch available models for the account */\n fetchAvailableModels: 'https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels',\n\n /** Fetch raw quota data */\n retrieveUserQuota: 'https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota',\n\n /** Fetch quota summary with weekly + session buckets */\n retrieveUserQuotaSummary: 'https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuotaSummary',\n} as const\n\nexport const CLOUD_CODE_DEFAULT_BODY = {\n metadata: {\n ideName: 'antigravity',\n extensionName: 'antigravity',\n locale: 'en',\n ideVersion: 'unknown',\n },\n}\n\nexport const OAUTH_CLIENT_ID = '764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com'\nexport const OAUTH_CLIENT_SECRET = 'd-FL95Q19q7MQmFpd7hHD0Ty'\nexport const OAUTH_SCOPES = [\n 'https://www.googleapis.com/auth/cloud-platform',\n].join(' ')\nexport const OAUTH_REDIRECT_URI = 'http://127.0.0.1:0/callback'\n","/**\n * Token storage for account credentials\n *\n * Stores OAuth tokens locally in the config directory.\n * Tokens are stored as plain JSON (local machine only).\n */\n\nimport { readFileSync, writeFileSync, existsSync, unlinkSync, mkdirSync } from 'fs'\nimport { join, dirname } from 'path'\nimport type { StoredTokens } from '../types.js'\nimport { getConfigDirPath, ensureDirs } from '../../core/config.js'\nimport { debug } from '../../core/logger.js'\n\nconst TOKENS_DIR = 'accounts'\n\ninterface TokenAccount {\n email: string\n tokens: StoredTokens\n addedAt: string\n}\n\ninterface TokenStore {\n accounts: TokenAccount[]\n activeEmail?: string\n}\n\nfunction getStorePath(): string {\n return join(getConfigDirPath(), TOKENS_DIR, 'tokens.json')\n}\n\nfunction loadStore(): TokenStore {\n const path = getStorePath()\n if (!existsSync(path)) return { accounts: [] }\n try {\n return JSON.parse(readFileSync(path, 'utf-8'))\n } catch {\n return { accounts: [] }\n }\n}\n\nfunction saveStore(store: TokenStore): void {\n ensureDirs()\n const storePath = getStorePath()\n mkdirSync(dirname(storePath), { recursive: true })\n writeFileSync(storePath, JSON.stringify(store, null, 2))\n debug('account-storage', `Saved ${store.accounts.length} account(s)`)\n}\n\n/**\n * Save tokens for an account\n */\nexport function saveAccountTokens(email: string, tokens: StoredTokens): void {\n const store = loadStore()\n const existing = store.accounts.findIndex(a => a.email === email)\n const account: TokenAccount = {\n email,\n tokens,\n addedAt: new Date().toISOString(),\n }\n\n if (existing >= 0) {\n store.accounts[existing] = account\n } else {\n store.accounts.push(account)\n }\n\n // Set as active if it's the only one\n if (store.accounts.length === 1) {\n store.activeEmail = email\n }\n\n saveStore(store)\n}\n\n/**\n * Get tokens for a specific account\n */\nexport function getAccountTokens(email: string): StoredTokens | null {\n const store = loadStore()\n const account = store.accounts.find(a => a.email === email)\n return account?.tokens || null\n}\n\n/**\n * Get the active account's tokens\n */\nexport function getActiveAccountTokens(): StoredTokens | null {\n const store = loadStore()\n if (!store.activeEmail) return null\n const account = store.accounts.find(a => a.email === store.activeEmail)\n return account?.tokens || null\n}\n\n/**\n * Set the active account\n */\nexport function setActiveAccount(email: string): boolean {\n const store = loadStore()\n if (!store.accounts.find(a => a.email === email)) return false\n store.activeEmail = email\n saveStore(store)\n return true\n}\n\n/**\n * Remove an account\n */\nexport function removeAccount(email: string): boolean {\n const store = loadStore()\n const idx = store.accounts.findIndex(a => a.email === email)\n if (idx < 0) return false\n store.accounts.splice(idx, 1)\n if (store.activeEmail === email) {\n store.activeEmail = store.accounts[0]?.email\n }\n saveStore(store)\n return true\n}\n\n/**\n * List all stored accounts\n */\nexport function listAccounts(): Array<{ email: string; isActive: boolean; addedAt: string }> {\n const store = loadStore()\n return store.accounts.map(a => ({\n email: a.email,\n isActive: a.email === store.activeEmail,\n addedAt: a.addedAt,\n }))\n}\n\n/**\n * Get all stored tokens (for multi-account fetch)\n */\nexport function getAllAccountTokens(): StoredTokens[] {\n const store = loadStore()\n return store.accounts.map(a => a.tokens)\n}\n","/**\n * Config file management — reads/writes app configuration\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs'\nimport { join } from 'path'\nimport { homedir } from 'os'\nimport type { AppConfig } from '../sdk/types.js'\nimport { debug } from './logger.js'\n\nconst CONFIG_DIR_NAME = 'when-does-my-quota-refresh'\n\nconst DEFAULT_CONFIG: AppConfig = {\n defaultMode: 'local',\n cacheTtlMs: 5 * 60 * 1000, // 5 minutes\n refreshIntervalMs: 5 * 60 * 1000,\n wakeupModels: ['claude-sonnet-4-5', 'gemini-3-flash', 'gemini-3-pro-low'],\n wakeupAccounts: [],\n wakeupMode: 'smart',\n wakeupIntervalHours: 6,\n wakeupDailyTimes: '9,17',\n notifications: true,\n plugins: [],\n daemon: {\n pollIntervalMs: 60 * 1000,\n enabled: false,\n },\n}\n\nfunction getConfigDir(): string {\n const home = homedir()\n switch (process.platform) {\n case 'darwin':\n return join(home, 'Library', 'Application Support', CONFIG_DIR_NAME)\n case 'win32':\n return join(process.env.APPDATA || join(home, 'AppData', 'Roaming'), CONFIG_DIR_NAME)\n default:\n return join(home, '.config', CONFIG_DIR_NAME)\n }\n}\n\nfunction getConfigPath(): string {\n return join(getConfigDir(), 'config.json')\n}\n\nfunction getDataDir(): string {\n return join(getConfigDir(), 'data')\n}\n\nexport function ensureDirs(): void {\n const configDir = getConfigDir()\n const dataDir = getDataDir()\n if (!existsSync(configDir)) mkdirSync(configDir, { recursive: true })\n if (!existsSync(dataDir)) mkdirSync(dataDir, { recursive: true })\n}\n\nexport function loadConfig(): AppConfig {\n try {\n const path = getConfigPath()\n if (!existsSync(path)) return DEFAULT_CONFIG\n const raw = readFileSync(path, 'utf-8')\n const parsed = JSON.parse(raw)\n debug('config', `Loaded config from ${path}`)\n return { ...DEFAULT_CONFIG, ...parsed }\n } catch (err) {\n debug('config', 'Failed to load config, using defaults', err)\n return DEFAULT_CONFIG\n }\n}\n\nexport function saveConfig(config: AppConfig): void {\n ensureDirs()\n const path = getConfigPath()\n writeFileSync(path, JSON.stringify(config, null, 2))\n debug('config', `Saved config to ${path}`)\n}\n\nexport function getConfigDirPath(): string {\n return getConfigDir()\n}\n\nexport function getDataDirPath(): string {\n return getDataDir()\n}\n\nexport { DEFAULT_CONFIG }\n","/**\n * Custom error types for when-does-my-quota-refresh\n */\n\nexport class SourceUnavailableError extends Error {\n constructor(source: string, reason?: string) {\n super(`Source \"${source}\" unavailable${reason ? `: ${reason}` : ''}`)\n this.name = 'SourceUnavailableError'\n }\n}\n\nexport class AuthError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'AuthError'\n }\n}\n\nexport class QuotaFetchError extends Error {\n constructor(source: string, reason?: string) {\n super(`Failed to fetch quota from \"${source}\"${reason ? `: ${reason}` : ''}`)\n this.name = 'QuotaFetchError'\n }\n}\n\nexport class ProcessNotFoundError extends Error {\n constructor() {\n super('Antigravity language server process not found')\n this.name = 'ProcessNotFoundError'\n }\n}\n\nexport class PortDiscoveryError extends Error {\n constructor(pid: number, platform: string) {\n super(`Failed to discover ports for PID ${pid} on ${platform}`)\n this.name = 'PortDiscoveryError'\n }\n}\n","/**\n * OAuth authentication flow for Google accounts\n */\n\nimport { OAuthClient } from '../../sources/oauth/client.js'\nimport { saveAccountTokens, setActiveAccount } from './storage.js'\nimport { debug } from '../../core/logger.js'\nimport { AuthError } from '../../core/errors.js'\nimport open from 'open'\nimport http from 'http'\nimport { URL } from 'url'\n\n/**\n * Start an interactive OAuth login flow\n *\n * Opens the browser for Google login, then captures the redirect\n * to exchange the authorization code for tokens.\n */\nexport async function loginAccount(): Promise<string> {\n const client = new OAuthClient()\n\n debug('auth', 'Starting OAuth login flow')\n\n // Start a temporary local server to catch the redirect\n let capturedRedirectUri = 'http://127.0.0.1:0/callback'\n const code = await new Promise<string>((resolve, reject) => {\n const server = http.createServer(async (req, res) => {\n const url = new URL(req.url || '/', `http://127.0.0.1`)\n const code = url.searchParams.get('code')\n\n if (code) {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })\n res.end(`\n <html><body style=\"font-family: sans-serif; text-align: center; padding: 50px;\">\n <h1>✅ Login successful!</h1>\n <p>You can close this tab and return to the terminal.</p>\n </body></html>\n `)\n server.close()\n resolve(code)\n } else {\n const error = url.searchParams.get('error')\n if (error) {\n res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' })\n res.end(`<h1>Login failed: ${error}</h1>`)\n server.close()\n reject(new AuthError(`OAuth error: ${error}`))\n } else {\n res.writeHead(404)\n res.end('Waiting for OAuth callback...')\n }\n }\n })\n\n server.listen(0, '127.0.0.1', () => {\n const addr = server.address()\n if (typeof addr === 'object' && addr) {\n capturedRedirectUri = `http://127.0.0.1:${addr.port}/callback`\n debug('auth', `Callback server on port ${addr.port}`)\n\n // Build auth URL with the actual port\n const authUrl = client.getAuthUrl(capturedRedirectUri)\n\n // Open browser\n open(authUrl).catch(() => {\n console.log(`\\nOpen this URL in your browser:\\n\\n${authUrl}\\n`)\n })\n }\n })\n\n // Timeout after 5 minutes\n setTimeout(() => {\n server.close()\n reject(new AuthError('Login timed out after 5 minutes'))\n }, 5 * 60 * 1000)\n })\n\n // Exchange code for tokens (use same redirect URI as the auth URL)\n const tokens = await client.exchangeCode(code, capturedRedirectUri)\n\n // Fetch the user's email from Google\n let email = tokens.email\n if (!email) {\n try {\n const userInfo = await client.fetchUserInfo()\n email = userInfo.email\n } catch (err) {\n debug('auth', `Failed to fetch user info: ${err}`)\n }\n }\n if (!email) {\n throw new AuthError('Could not determine user email from Google account')\n }\n tokens.email = email\n\n // Store tokens\n saveAccountTokens(email, tokens)\n setActiveAccount(email)\n\n debug('auth', `Logged in as ${email}`)\n return email\n}\n\n/**\n * Perform a manual login (headless/SSH mode)\n * Returns the auth URL for the user to open manually\n */\nexport function getManualLoginUrl(): string {\n const client = new OAuthClient()\n return client.getAuthUrl()\n}\n\n/**\n * Complete manual login with an authorization code\n */\nexport async function completeManualLogin(code: string): Promise<string> {\n const client = new OAuthClient()\n const tokens = await client.exchangeCode(code)\n\n // Fetch the user's email from Google\n let email = tokens.email\n if (!email) {\n try {\n const userInfo = await client.fetchUserInfo()\n email = userInfo.email\n } catch (err) {\n debug('auth', `Failed to fetch user info: ${err}`)\n }\n }\n if (!email) {\n throw new AuthError('Could not determine user email from Google account')\n }\n tokens.email = email\n saveAccountTokens(email, tokens)\n setActiveAccount(email)\n return email\n}\n"],"mappings":"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","names":["readFileSync","writeFileSync","existsSync","mkdirSync","join","join","existsSync","readFileSync","mkdirSync","writeFileSync","URL","code"]}
|
package/dist/cli/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import "../chunk-H7BEO7IF.js";
|
|
2
3
|
import {
|
|
3
4
|
OAuthClient,
|
|
4
5
|
SourceUnavailableError,
|
|
@@ -15,7 +16,7 @@ import {
|
|
|
15
16
|
saveConfig,
|
|
16
17
|
setActiveAccount,
|
|
17
18
|
setVerbose
|
|
18
|
-
} from "../chunk-
|
|
19
|
+
} from "../chunk-VLP22VAR.js";
|
|
19
20
|
|
|
20
21
|
// src/cli/index.ts
|
|
21
22
|
import { Command } from "commander";
|
|
@@ -423,7 +424,7 @@ var ConnectClient = class {
|
|
|
423
424
|
* Fetch model configs (last-resort fallback)
|
|
424
425
|
*/
|
|
425
426
|
async fetchModelConfigs() {
|
|
426
|
-
debug("connect-client", "Fetching
|
|
427
|
+
debug("connect-client", "Fetching GetCommandModelConfigs");
|
|
427
428
|
try {
|
|
428
429
|
return await this.request("POST", ENDPOINTS.modelConfigs, {
|
|
429
430
|
metadata: {
|
|
@@ -570,11 +571,11 @@ var ConnectClient = class {
|
|
|
570
571
|
};
|
|
571
572
|
|
|
572
573
|
// src/sources/local/parser.ts
|
|
573
|
-
function parseQuotaSummary(summary, email) {
|
|
574
|
+
function parseQuotaSummary(summary, email, method = "local") {
|
|
574
575
|
debug("parser", `Parsing quota summary: ${summary.groups.length} groups`);
|
|
575
576
|
return {
|
|
576
577
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
577
|
-
method
|
|
578
|
+
method,
|
|
578
579
|
email,
|
|
579
580
|
groups: summary.groups.map((g) => ({
|
|
580
581
|
displayName: g.displayName,
|
|
@@ -589,11 +590,11 @@ function parseQuotaSummary(summary, email) {
|
|
|
589
590
|
}))
|
|
590
591
|
};
|
|
591
592
|
}
|
|
592
|
-
function parseUserStatus(userStatus) {
|
|
593
|
+
function parseUserStatus(userStatus, method = "local") {
|
|
593
594
|
debug("parser", "Parsing GetUserStatus fallback");
|
|
594
595
|
const snapshot = {
|
|
595
596
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
596
|
-
method
|
|
597
|
+
method,
|
|
597
598
|
email: userStatus.email,
|
|
598
599
|
groups: []
|
|
599
600
|
};
|
|
@@ -667,7 +668,7 @@ function isGeminiModel(modelId) {
|
|
|
667
668
|
}
|
|
668
669
|
function detectAutocomplete(modelId, label) {
|
|
669
670
|
const text = `${modelId} ${label || ""}`.toLowerCase();
|
|
670
|
-
return text.includes("autocomplete")
|
|
671
|
+
return text.includes("autocomplete");
|
|
671
672
|
}
|
|
672
673
|
function clampFraction(value) {
|
|
673
674
|
if (value === void 0 || value === null) return 1;
|
|
@@ -841,10 +842,10 @@ var CliSource = class {
|
|
|
841
842
|
const summary = await client.fetchQuotaSummary();
|
|
842
843
|
if (summary && summary.groups.length > 0) {
|
|
843
844
|
const email = (await client.fetchUserStatus())?.email;
|
|
844
|
-
return parseQuotaSummary(summary, email);
|
|
845
|
+
return parseQuotaSummary(summary, email, "cli");
|
|
845
846
|
}
|
|
846
847
|
const userStatus = await client.fetchUserStatus();
|
|
847
|
-
if (userStatus) return parseUserStatus(userStatus);
|
|
848
|
+
if (userStatus) return parseUserStatus(userStatus, "cli");
|
|
848
849
|
} catch {
|
|
849
850
|
}
|
|
850
851
|
}
|
|
@@ -903,20 +904,25 @@ var OAuthSource = class {
|
|
|
903
904
|
}
|
|
904
905
|
async fetchQuota() {
|
|
905
906
|
debug("oauth", "Fetching quota via Cloud Code API");
|
|
907
|
+
let email;
|
|
908
|
+
try {
|
|
909
|
+
const userInfo = await this.client.fetchUserInfo();
|
|
910
|
+
email = userInfo.email;
|
|
911
|
+
} catch {
|
|
912
|
+
debug("oauth", "Could not fetch user info for email");
|
|
913
|
+
}
|
|
906
914
|
try {
|
|
907
915
|
const summaryRaw = await this.client.fetchQuotaSummary();
|
|
908
916
|
const summary = this.parseRemoteSummary(summaryRaw);
|
|
909
917
|
if (summary && summary.groups.length > 0) {
|
|
910
|
-
const statusRaw2 = await this.client.fetchUserStatus();
|
|
911
|
-
const email = this.extractEmail(statusRaw2);
|
|
912
918
|
debug("oauth", "Got quota summary via OAuth");
|
|
913
|
-
return parseQuotaSummary(summary, email);
|
|
919
|
+
return parseQuotaSummary(summary, email, "oauth");
|
|
914
920
|
}
|
|
915
921
|
const statusRaw = await this.client.fetchUserStatus();
|
|
916
922
|
const status = this.parseRemoteStatus(statusRaw);
|
|
917
923
|
if (status) {
|
|
918
924
|
debug("oauth", "Got user status via OAuth");
|
|
919
|
-
return parseUserStatus(status);
|
|
925
|
+
return parseUserStatus(status, "oauth");
|
|
920
926
|
}
|
|
921
927
|
} catch (err) {
|
|
922
928
|
debug("oauth", `Fetch failed: ${err}`);
|
|
@@ -950,13 +956,12 @@ var OAuthSource = class {
|
|
|
950
956
|
*/
|
|
951
957
|
parseRemoteStatus(raw) {
|
|
952
958
|
if (typeof raw !== "object" || raw === null) return null;
|
|
953
|
-
return { raw };
|
|
954
|
-
}
|
|
955
|
-
extractEmail(raw) {
|
|
956
|
-
if (typeof raw !== "object" || raw === null) return void 0;
|
|
957
959
|
const data = raw;
|
|
958
|
-
const userStatus = data.userStatus;
|
|
959
|
-
return
|
|
960
|
+
const userStatus = data.userStatus || data;
|
|
961
|
+
return {
|
|
962
|
+
email: userStatus.email,
|
|
963
|
+
raw
|
|
964
|
+
};
|
|
960
965
|
}
|
|
961
966
|
};
|
|
962
967
|
|
|
@@ -1230,17 +1235,160 @@ function closeStore() {
|
|
|
1230
1235
|
}
|
|
1231
1236
|
}
|
|
1232
1237
|
|
|
1238
|
+
// src/plugins/builtin/notifications.ts
|
|
1239
|
+
var NotificationPlugin = class {
|
|
1240
|
+
name = "notifications";
|
|
1241
|
+
version = "1.0.0";
|
|
1242
|
+
notifier = null;
|
|
1243
|
+
notifiedLow = /* @__PURE__ */ new Set();
|
|
1244
|
+
async onInit(ctx) {
|
|
1245
|
+
try {
|
|
1246
|
+
const { default: notifier } = await import("node-notifier");
|
|
1247
|
+
this.notifier = notifier;
|
|
1248
|
+
debug("notifications", "Notification plugin initialized");
|
|
1249
|
+
} catch {
|
|
1250
|
+
debug("notifications", "node-notifier not available, notifications disabled");
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
async onQuotaUpdate(snapshot, ctx) {
|
|
1254
|
+
for (const group of snapshot.groups) {
|
|
1255
|
+
for (const bucket of group.buckets) {
|
|
1256
|
+
if (bucket.remainingFraction > 0.8) {
|
|
1257
|
+
this.notifiedLow.delete(`${group.displayName}:${bucket.displayName}`);
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
async onQuotaLow(group, bucket, remaining, ctx) {
|
|
1263
|
+
const key = `${group}:${bucket}`;
|
|
1264
|
+
if (this.notifiedLow.has(key)) return;
|
|
1265
|
+
const pct = Math.round(remaining * 100);
|
|
1266
|
+
const title = "when-does-my-quota-refresh";
|
|
1267
|
+
const message = `\u26A0\uFE0F Low quota: ${group} \u2014 ${bucket} at ${pct}%`;
|
|
1268
|
+
ctx.log(message);
|
|
1269
|
+
this.notify(title, message);
|
|
1270
|
+
this.notifiedLow.add(key);
|
|
1271
|
+
}
|
|
1272
|
+
async onReset(group, nextReset, ctx) {
|
|
1273
|
+
const title = "when-does-my-quota-refresh";
|
|
1274
|
+
const message = `\u2705 ${group} quota has reset!`;
|
|
1275
|
+
ctx.log(message);
|
|
1276
|
+
this.notify(title, message);
|
|
1277
|
+
}
|
|
1278
|
+
notify(title, message) {
|
|
1279
|
+
if (!this.notifier) return;
|
|
1280
|
+
try {
|
|
1281
|
+
this.notifier.notify({ title, message, timeout: 5 });
|
|
1282
|
+
} catch (err) {
|
|
1283
|
+
debug("notifications", `Notification failed: ${err}`);
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
};
|
|
1287
|
+
|
|
1288
|
+
// src/plugins/index.ts
|
|
1289
|
+
var PluginRegistry = class {
|
|
1290
|
+
plugins = [];
|
|
1291
|
+
context;
|
|
1292
|
+
constructor(context) {
|
|
1293
|
+
this.context = {
|
|
1294
|
+
notify: context?.notify || (() => {
|
|
1295
|
+
}),
|
|
1296
|
+
log: context?.log || ((msg) => console.log(msg))
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
/**
|
|
1300
|
+
* Register a plugin
|
|
1301
|
+
*/
|
|
1302
|
+
async register(plugin) {
|
|
1303
|
+
this.plugins.push(plugin);
|
|
1304
|
+
if (plugin.onInit) {
|
|
1305
|
+
await plugin.onInit(this.context);
|
|
1306
|
+
}
|
|
1307
|
+
debug("plugins", `Registered: ${plugin.name}@${plugin.version}`);
|
|
1308
|
+
}
|
|
1309
|
+
/**
|
|
1310
|
+
* Load built-in plugins
|
|
1311
|
+
*/
|
|
1312
|
+
async loadBuiltins() {
|
|
1313
|
+
await this.register(new NotificationPlugin());
|
|
1314
|
+
}
|
|
1315
|
+
/**
|
|
1316
|
+
* Notify all plugins of a quota update
|
|
1317
|
+
*/
|
|
1318
|
+
async notifyQuotaUpdate(snapshot) {
|
|
1319
|
+
for (const plugin of this.plugins) {
|
|
1320
|
+
if (plugin.onQuotaUpdate) {
|
|
1321
|
+
try {
|
|
1322
|
+
await plugin.onQuotaUpdate(snapshot, this.context);
|
|
1323
|
+
} catch (err) {
|
|
1324
|
+
debug("plugins", `Error in ${plugin.name}.onQuotaUpdate: ${err}`);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
for (const group of snapshot.groups) {
|
|
1329
|
+
for (const bucket of group.buckets) {
|
|
1330
|
+
if (bucket.remainingFraction < 0.15) {
|
|
1331
|
+
await this.notifyQuotaLow(group.displayName, bucket.displayName, bucket.remainingFraction);
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
/**
|
|
1337
|
+
* Notify all plugins of low quota
|
|
1338
|
+
*/
|
|
1339
|
+
async notifyQuotaLow(group, bucket, remaining) {
|
|
1340
|
+
for (const plugin of this.plugins) {
|
|
1341
|
+
if (plugin.onQuotaLow) {
|
|
1342
|
+
try {
|
|
1343
|
+
await plugin.onQuotaLow(group, bucket, remaining, this.context);
|
|
1344
|
+
} catch (err) {
|
|
1345
|
+
debug("plugins", `Error in ${plugin.name}.onQuotaLow: ${err}`);
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
/**
|
|
1351
|
+
* Destroy all plugins
|
|
1352
|
+
*/
|
|
1353
|
+
async destroy() {
|
|
1354
|
+
for (const plugin of this.plugins) {
|
|
1355
|
+
if (plugin.onDestroy) {
|
|
1356
|
+
try {
|
|
1357
|
+
await plugin.onDestroy();
|
|
1358
|
+
} catch (err) {
|
|
1359
|
+
debug("plugins", `Error in ${plugin.name}.onDestroy: ${err}`);
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
this.plugins = [];
|
|
1364
|
+
}
|
|
1365
|
+
/**
|
|
1366
|
+
* Get registered plugin names
|
|
1367
|
+
*/
|
|
1368
|
+
getNames() {
|
|
1369
|
+
return this.plugins.map((p) => p.name);
|
|
1370
|
+
}
|
|
1371
|
+
};
|
|
1372
|
+
|
|
1233
1373
|
// src/sdk/quota.ts
|
|
1234
1374
|
var QuotaClient = class {
|
|
1235
1375
|
registry;
|
|
1236
1376
|
cache;
|
|
1377
|
+
plugins;
|
|
1237
1378
|
verbose;
|
|
1238
1379
|
constructor(options) {
|
|
1239
1380
|
this.verbose = options?.verbose || false;
|
|
1240
|
-
|
|
1381
|
+
if (options?.verbose !== void 0) {
|
|
1382
|
+
setVerbose(this.verbose);
|
|
1383
|
+
}
|
|
1241
1384
|
const config = loadConfig();
|
|
1242
1385
|
this.registry = new SourceRegistry();
|
|
1243
1386
|
this.cache = new QuotaCache(options?.cacheTtlMs || config.cacheTtlMs);
|
|
1387
|
+
this.plugins = new PluginRegistry();
|
|
1388
|
+
if (config.notifications) {
|
|
1389
|
+
this.plugins.loadBuiltins().catch(() => {
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1244
1392
|
this.registerOAuthSources();
|
|
1245
1393
|
}
|
|
1246
1394
|
/**
|
|
@@ -1251,11 +1399,19 @@ var QuotaClient = class {
|
|
|
1251
1399
|
return this.fetchAllAccounts(options);
|
|
1252
1400
|
}
|
|
1253
1401
|
if (!options?.refresh) {
|
|
1402
|
+
const tokens = getAllAccountTokens();
|
|
1403
|
+
for (const token of tokens) {
|
|
1404
|
+
if (!token.email) continue;
|
|
1405
|
+
const cached = this.cache.get(token.email, options?.source || "auto");
|
|
1406
|
+
if (cached) return cached;
|
|
1407
|
+
}
|
|
1254
1408
|
}
|
|
1255
1409
|
const snapshot = await this.registry.fetchQuota(options?.source);
|
|
1256
|
-
if (snapshot.email) {
|
|
1410
|
+
if (snapshot.email && snapshot.email !== "unknown") {
|
|
1257
1411
|
this.cache.set(snapshot.email, snapshot.method, snapshot);
|
|
1258
1412
|
storeSnapshot(snapshot);
|
|
1413
|
+
this.plugins.notifyQuotaUpdate(snapshot).catch(() => {
|
|
1414
|
+
});
|
|
1259
1415
|
}
|
|
1260
1416
|
return snapshot;
|
|
1261
1417
|
}
|
|
@@ -1659,8 +1815,8 @@ function registerAccountsCommand(program2) {
|
|
|
1659
1815
|
accounts.command("add").description("Login a new Google account").option("--manual", "Manual login for headless/SSH (get URL instead of browser)").action(async (opts) => {
|
|
1660
1816
|
try {
|
|
1661
1817
|
if (opts.manual) {
|
|
1662
|
-
const { getManualLoginUrl
|
|
1663
|
-
const url =
|
|
1818
|
+
const { getManualLoginUrl, completeManualLogin } = await import("../auth-GX4ZIG5O.js");
|
|
1819
|
+
const url = getManualLoginUrl();
|
|
1664
1820
|
console.log(chalk6.bold("\nOpen this URL in your browser:\n"));
|
|
1665
1821
|
console.log(chalk6.cyan(url));
|
|
1666
1822
|
console.log(chalk6.dim("\nPaste the authorization code here:"));
|
|
@@ -1669,7 +1825,7 @@ function registerAccountsCommand(program2) {
|
|
|
1669
1825
|
name: "code",
|
|
1670
1826
|
message: "Authorization code:"
|
|
1671
1827
|
}]);
|
|
1672
|
-
const email = await
|
|
1828
|
+
const email = await completeManualLogin(code);
|
|
1673
1829
|
console.log(chalk6.green(`
|
|
1674
1830
|
\u2713 Logged in as ${email}`));
|
|
1675
1831
|
} else {
|
|
@@ -2086,7 +2242,15 @@ function registerWakeupCommand(program2) {
|
|
|
2086
2242
|
default: true
|
|
2087
2243
|
}
|
|
2088
2244
|
]);
|
|
2089
|
-
config.
|
|
2245
|
+
config.wakeupMode = answers.mode;
|
|
2246
|
+
if (answers.intervalHours) config.wakeupIntervalHours = answers.intervalHours;
|
|
2247
|
+
if (answers.dailyTimes) config.wakeupDailyTimes = answers.dailyTimes;
|
|
2248
|
+
if (!answers.allAccounts) {
|
|
2249
|
+
const { listAccounts: listAccounts2 } = await import("../accounts-FH6AKZT7.js");
|
|
2250
|
+
config.wakeupAccounts = listAccounts2().map((a) => a.email);
|
|
2251
|
+
} else {
|
|
2252
|
+
config.wakeupAccounts = [];
|
|
2253
|
+
}
|
|
2090
2254
|
saveConfig(config);
|
|
2091
2255
|
console.log(chalk11.green("\n \u2713 Configuration saved"));
|
|
2092
2256
|
console.log(chalk11.dim(` Run \`aq wakeup install\` to activate`));
|
|
@@ -2120,8 +2284,11 @@ function registerWakeupCommand(program2) {
|
|
|
2120
2284
|
wakeup.command("status").description("Check wakeup status").action(() => {
|
|
2121
2285
|
const config = loadConfig();
|
|
2122
2286
|
console.log(chalk11.bold("\n Wakeup Status\n"));
|
|
2287
|
+
console.log(` Mode: ${config.wakeupMode}`);
|
|
2123
2288
|
console.log(` Models: ${config.wakeupModels.join(", ")}`);
|
|
2124
2289
|
console.log(` Accounts: ${config.wakeupAccounts.length > 0 ? config.wakeupAccounts.join(", ") : "all"}`);
|
|
2290
|
+
if (config.wakeupMode === "interval") console.log(` Interval: every ${config.wakeupIntervalHours}h`);
|
|
2291
|
+
if (config.wakeupMode === "daily") console.log(` Daily at: ${config.wakeupDailyTimes}`);
|
|
2125
2292
|
if (isWindows()) {
|
|
2126
2293
|
const installed = checkWindowsTask();
|
|
2127
2294
|
console.log(` Scheduler: ${installed ? chalk11.green("Installed") : chalk11.dim("Not installed")}`);
|
|
@@ -2142,12 +2309,32 @@ function registerWakeupCommand(program2) {
|
|
|
2142
2309
|
}
|
|
2143
2310
|
});
|
|
2144
2311
|
}
|
|
2312
|
+
function escapeShellArg(arg) {
|
|
2313
|
+
return arg.replace(/'/g, "'\\''");
|
|
2314
|
+
}
|
|
2145
2315
|
function installCrontab() {
|
|
2146
2316
|
const aqPath = process.argv[1];
|
|
2317
|
+
const safeAqPath = escapeShellArg(aqPath);
|
|
2147
2318
|
const config = loadConfig();
|
|
2148
2319
|
uninstallCrontab();
|
|
2149
|
-
const intervalHours = 6;
|
|
2150
|
-
|
|
2320
|
+
const intervalHours = config.wakeupIntervalHours || 6;
|
|
2321
|
+
let cronLine;
|
|
2322
|
+
if (config.wakeupMode === "daily" && config.wakeupDailyTimes) {
|
|
2323
|
+
const hours = config.wakeupDailyTimes.split(",").map((h) => parseInt(h.trim(), 10)).filter((h) => !isNaN(h));
|
|
2324
|
+
for (const hour of hours) {
|
|
2325
|
+
cronLine = `0 ${hour} * * * "${safeAqPath}" quota --refresh --json > /dev/null 2>&1 ${CRON_MARKER}`;
|
|
2326
|
+
try {
|
|
2327
|
+
const existing = execSync("crontab -l 2>/dev/null", { encoding: "utf-8" }).trim();
|
|
2328
|
+
const newCron = existing ? `${existing}
|
|
2329
|
+
${cronLine}` : cronLine;
|
|
2330
|
+
execSync(`echo '${newCron}' | crontab -`, { encoding: "utf-8" });
|
|
2331
|
+
} catch {
|
|
2332
|
+
execSync(`echo '${cronLine}' | crontab -`, { encoding: "utf-8" });
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
return;
|
|
2336
|
+
}
|
|
2337
|
+
cronLine = `0 */${intervalHours} * * * "${safeAqPath}" quota --refresh --json > /dev/null 2>&1 ${CRON_MARKER}`;
|
|
2151
2338
|
try {
|
|
2152
2339
|
const existing = execSync("crontab -l 2>/dev/null", { encoding: "utf-8" }).trim();
|
|
2153
2340
|
const newCron = existing ? `${existing}
|
|
@@ -2161,7 +2348,8 @@ function uninstallCrontab() {
|
|
|
2161
2348
|
try {
|
|
2162
2349
|
const existing = execSync("crontab -l 2>/dev/null", { encoding: "utf-8" });
|
|
2163
2350
|
const filtered = existing.split("\n").filter((l) => !l.includes(CRON_MARKER)).join("\n").trim();
|
|
2164
|
-
execSync(`
|
|
2351
|
+
execSync(`printf '%s
|
|
2352
|
+
' '${filtered.replace(/'/g, "'\\''")}' | crontab -`, { encoding: "utf-8" });
|
|
2165
2353
|
} catch {
|
|
2166
2354
|
}
|
|
2167
2355
|
}
|
|
@@ -2177,12 +2365,14 @@ function installWindowsTask() {
|
|
|
2177
2365
|
const aqPath = process.argv[1];
|
|
2178
2366
|
const xmlPath = join2(homedir(), "when-does-my-quota-refresh-wakeup.xml");
|
|
2179
2367
|
uninstallWindowsTask();
|
|
2368
|
+
const config = loadConfig();
|
|
2369
|
+
const intervalHours = config.wakeupIntervalHours || 6;
|
|
2180
2370
|
const xml = `<?xml version="1.0" encoding="UTF-16"?>
|
|
2181
2371
|
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
|
2182
2372
|
<Triggers>
|
|
2183
2373
|
<TimeTrigger>
|
|
2184
2374
|
<Repetition>
|
|
2185
|
-
<Interval>
|
|
2375
|
+
<Interval>PT${intervalHours}H</Interval>
|
|
2186
2376
|
</Repetition>
|
|
2187
2377
|
<StartBoundary>2024-01-01T09:00:00</StartBoundary>
|
|
2188
2378
|
</TimeTrigger>
|