when-does-my-quota-refresh 1.0.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.
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ completeManualLogin,
4
+ getManualLoginUrl,
5
+ loginAccount
6
+ } from "./chunk-YZVX5QIP.js";
7
+ export {
8
+ completeManualLogin,
9
+ getManualLoginUrl,
10
+ loginAccount
11
+ };
12
+ //# sourceMappingURL=auth-S43EEJYA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,487 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/sources/oauth/client.ts
4
+ import https from "https";
5
+ import { URL } from "url";
6
+
7
+ // src/sources/cloud-code-api.ts
8
+ var CLOUD_CODE_ENDPOINTS = {
9
+ /** Load code assist configuration */
10
+ loadCodeAssist: "https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist",
11
+ /** Onboard a new user */
12
+ onboardUser: "https://cloudcode-pa.googleapis.com/v1internal:onboardUser",
13
+ /** Fetch available models for the account */
14
+ fetchAvailableModels: "https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels",
15
+ /** Fetch raw quota data */
16
+ retrieveUserQuota: "https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota",
17
+ /** Fetch quota summary with weekly + session buckets */
18
+ retrieveUserQuotaSummary: "https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuotaSummary"
19
+ };
20
+ var CLOUD_CODE_DEFAULT_BODY = {
21
+ metadata: {
22
+ ideName: "antigravity",
23
+ extensionName: "antigravity",
24
+ locale: "en",
25
+ ideVersion: "unknown"
26
+ }
27
+ };
28
+ var OAUTH_CLIENT_ID = "764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com";
29
+ var OAUTH_CLIENT_SECRET = "d-FL95Q19q7MQmFpd7hHD0Ty";
30
+ var OAUTH_SCOPES = [
31
+ "https://www.googleapis.com/auth/cloud-platform",
32
+ "https://www.googleapis.com/auth/cloudcode"
33
+ ].join(" ");
34
+
35
+ // src/sources/oauth/client.ts
36
+ var OAuthClient = class {
37
+ tokens = null;
38
+ constructor(tokens) {
39
+ this.tokens = tokens || null;
40
+ }
41
+ /**
42
+ * Generate the OAuth authorization URL for user login
43
+ */
44
+ getAuthUrl() {
45
+ const params = new URLSearchParams({
46
+ client_id: OAUTH_CLIENT_ID,
47
+ redirect_uri: "http://127.0.0.1:0/callback",
48
+ response_type: "code",
49
+ scope: OAUTH_SCOPES,
50
+ access_type: "offline",
51
+ prompt: "consent"
52
+ });
53
+ return `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`;
54
+ }
55
+ /**
56
+ * Exchange an authorization code for tokens
57
+ */
58
+ async exchangeCode(code) {
59
+ const body = new URLSearchParams({
60
+ code,
61
+ client_id: OAUTH_CLIENT_ID,
62
+ client_secret: OAUTH_CLIENT_SECRET,
63
+ redirect_uri: "http://127.0.0.1:0/callback",
64
+ grant_type: "authorization_code"
65
+ });
66
+ const response = await this.postUrlEncoded("https://oauth2.googleapis.com/token", body);
67
+ const data = response;
68
+ this.tokens = {
69
+ accessToken: data.access_token,
70
+ refreshToken: data.refresh_token || "",
71
+ expiresAt: Date.now() + data.expires_in * 1e3
72
+ };
73
+ return this.tokens;
74
+ }
75
+ /**
76
+ * Refresh the access token
77
+ */
78
+ async refreshAccessToken() {
79
+ if (!this.tokens?.refreshToken) {
80
+ throw new Error("No refresh token available");
81
+ }
82
+ const body = new URLSearchParams({
83
+ client_id: OAUTH_CLIENT_ID,
84
+ client_secret: OAUTH_CLIENT_SECRET,
85
+ refresh_token: this.tokens.refreshToken,
86
+ grant_type: "refresh_token"
87
+ });
88
+ const response = await this.postUrlEncoded("https://oauth2.googleapis.com/token", body);
89
+ const data = response;
90
+ this.tokens = {
91
+ ...this.tokens,
92
+ accessToken: data.access_token,
93
+ expiresAt: Date.now() + data.expires_in * 1e3
94
+ };
95
+ return this.tokens;
96
+ }
97
+ /**
98
+ * Get a valid access token, refreshing if necessary
99
+ */
100
+ async getAccessToken() {
101
+ if (!this.tokens) throw new Error("Not authenticated");
102
+ if (Date.now() >= this.tokens.expiresAt - 6e4) {
103
+ await this.refreshAccessToken();
104
+ }
105
+ return this.tokens.accessToken;
106
+ }
107
+ /**
108
+ * Get stored tokens
109
+ */
110
+ getTokens() {
111
+ return this.tokens;
112
+ }
113
+ /**
114
+ * Make an authenticated POST request to the Cloud Code API
115
+ */
116
+ async fetchQuotaSummary() {
117
+ const token = await this.getAccessToken();
118
+ return this.authenticatedPost(
119
+ CLOUD_CODE_ENDPOINTS.retrieveUserQuotaSummary,
120
+ CLOUD_CODE_DEFAULT_BODY,
121
+ token
122
+ );
123
+ }
124
+ async fetchUserStatus() {
125
+ const token = await this.getAccessToken();
126
+ return this.authenticatedPost(
127
+ CLOUD_CODE_ENDPOINTS.loadCodeAssist,
128
+ CLOUD_CODE_DEFAULT_BODY,
129
+ token
130
+ );
131
+ }
132
+ async fetchAvailableModels() {
133
+ const token = await this.getAccessToken();
134
+ return this.authenticatedPost(
135
+ CLOUD_CODE_ENDPOINTS.fetchAvailableModels,
136
+ CLOUD_CODE_DEFAULT_BODY,
137
+ token
138
+ );
139
+ }
140
+ // ── HTTP Helpers ────────────────────────────────────────────────
141
+ authenticatedPost(url, body, token) {
142
+ return new Promise((resolve, reject) => {
143
+ const parsed = new URL(url);
144
+ const data = JSON.stringify(body);
145
+ const options = {
146
+ hostname: parsed.hostname,
147
+ path: parsed.pathname,
148
+ method: "POST",
149
+ headers: {
150
+ "Content-Type": "application/json",
151
+ "Authorization": `Bearer ${token}`,
152
+ "Content-Length": Buffer.byteLength(data)
153
+ },
154
+ timeout: 1e4
155
+ };
156
+ const req = https.request(options, (res) => {
157
+ let responseData = "";
158
+ res.on("data", (chunk) => {
159
+ responseData += chunk;
160
+ });
161
+ res.on("end", () => {
162
+ try {
163
+ resolve(JSON.parse(responseData));
164
+ } catch {
165
+ reject(new Error(`Invalid JSON: ${responseData.slice(0, 200)}`));
166
+ }
167
+ });
168
+ });
169
+ req.on("error", reject);
170
+ req.on("timeout", () => {
171
+ req.destroy();
172
+ reject(new Error("Timeout"));
173
+ });
174
+ req.write(data);
175
+ req.end();
176
+ });
177
+ }
178
+ postUrlEncoded(url, body) {
179
+ return new Promise((resolve, reject) => {
180
+ const parsed = new URL(url);
181
+ const data = body.toString();
182
+ const options = {
183
+ hostname: parsed.hostname,
184
+ path: parsed.pathname,
185
+ method: "POST",
186
+ headers: {
187
+ "Content-Type": "application/x-www-form-urlencoded",
188
+ "Content-Length": Buffer.byteLength(data)
189
+ },
190
+ timeout: 1e4
191
+ };
192
+ const req = https.request(options, (res) => {
193
+ let responseData = "";
194
+ res.on("data", (chunk) => {
195
+ responseData += chunk;
196
+ });
197
+ res.on("end", () => {
198
+ try {
199
+ resolve(JSON.parse(responseData));
200
+ } catch {
201
+ reject(new Error(`Invalid JSON: ${responseData.slice(0, 200)}`));
202
+ }
203
+ });
204
+ });
205
+ req.on("error", reject);
206
+ req.on("timeout", () => {
207
+ req.destroy();
208
+ reject(new Error("Timeout"));
209
+ });
210
+ req.write(data);
211
+ req.end();
212
+ });
213
+ }
214
+ };
215
+
216
+ // src/sdk/accounts/storage.ts
217
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
218
+ import { join as join2 } from "path";
219
+
220
+ // src/core/config.ts
221
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
222
+ import { join } from "path";
223
+ import { homedir } from "os";
224
+
225
+ // src/core/logger.ts
226
+ var _verbose = false;
227
+ function setVerbose(verbose) {
228
+ _verbose = verbose;
229
+ }
230
+ function debug(module, msg, data) {
231
+ if (!_verbose) return;
232
+ const prefix = `[${module}]`;
233
+ if (data !== void 0) {
234
+ console.error(`${prefix} ${msg}`, data);
235
+ } else {
236
+ console.error(`${prefix} ${msg}`);
237
+ }
238
+ }
239
+
240
+ // src/core/config.ts
241
+ var CONFIG_DIR_NAME = "when-does-my-quota-refresh";
242
+ var DEFAULT_CONFIG = {
243
+ defaultMode: "local",
244
+ cacheTtlMs: 5 * 60 * 1e3,
245
+ // 5 minutes
246
+ refreshIntervalMs: 5 * 60 * 1e3,
247
+ wakeupModels: ["claude-sonnet-4-5", "gemini-3-flash", "gemini-3-pro-low"],
248
+ wakeupAccounts: [],
249
+ notifications: true,
250
+ plugins: [],
251
+ daemon: {
252
+ pollIntervalMs: 60 * 1e3,
253
+ enabled: false
254
+ }
255
+ };
256
+ function getConfigDir() {
257
+ const home = homedir();
258
+ switch (process.platform) {
259
+ case "darwin":
260
+ return join(home, "Library", "Application Support", CONFIG_DIR_NAME);
261
+ case "win32":
262
+ return join(process.env.APPDATA || join(home, "AppData", "Roaming"), CONFIG_DIR_NAME);
263
+ default:
264
+ return join(home, ".config", CONFIG_DIR_NAME);
265
+ }
266
+ }
267
+ function getConfigPath() {
268
+ return join(getConfigDir(), "config.json");
269
+ }
270
+ function getDataDir() {
271
+ return join(getConfigDir(), "data");
272
+ }
273
+ function ensureDirs() {
274
+ const configDir = getConfigDir();
275
+ const dataDir = getDataDir();
276
+ if (!existsSync(configDir)) mkdirSync(configDir, { recursive: true });
277
+ if (!existsSync(dataDir)) mkdirSync(dataDir, { recursive: true });
278
+ }
279
+ function loadConfig() {
280
+ try {
281
+ const path = getConfigPath();
282
+ if (!existsSync(path)) return DEFAULT_CONFIG;
283
+ const raw = readFileSync(path, "utf-8");
284
+ const parsed = JSON.parse(raw);
285
+ debug("config", `Loaded config from ${path}`);
286
+ return { ...DEFAULT_CONFIG, ...parsed };
287
+ } catch (err) {
288
+ debug("config", "Failed to load config, using defaults", err);
289
+ return DEFAULT_CONFIG;
290
+ }
291
+ }
292
+ function saveConfig(config) {
293
+ ensureDirs();
294
+ const path = getConfigPath();
295
+ writeFileSync(path, JSON.stringify(config, null, 2));
296
+ debug("config", `Saved config to ${path}`);
297
+ }
298
+ function getConfigDirPath() {
299
+ return getConfigDir();
300
+ }
301
+ function getDataDirPath() {
302
+ return getDataDir();
303
+ }
304
+
305
+ // src/sdk/accounts/storage.ts
306
+ var TOKENS_DIR = "accounts";
307
+ function getStorePath() {
308
+ return join2(getConfigDirPath(), TOKENS_DIR, "tokens.json");
309
+ }
310
+ function loadStore() {
311
+ const path = getStorePath();
312
+ if (!existsSync2(path)) return { accounts: [] };
313
+ try {
314
+ return JSON.parse(readFileSync2(path, "utf-8"));
315
+ } catch {
316
+ return { accounts: [] };
317
+ }
318
+ }
319
+ function saveStore(store) {
320
+ ensureDirs();
321
+ writeFileSync2(getStorePath(), JSON.stringify(store, null, 2));
322
+ debug("account-storage", `Saved ${store.accounts.length} account(s)`);
323
+ }
324
+ function saveAccountTokens(email, tokens) {
325
+ const store = loadStore();
326
+ const existing = store.accounts.findIndex((a) => a.email === email);
327
+ const account = {
328
+ email,
329
+ tokens,
330
+ addedAt: (/* @__PURE__ */ new Date()).toISOString()
331
+ };
332
+ if (existing >= 0) {
333
+ store.accounts[existing] = account;
334
+ } else {
335
+ store.accounts.push(account);
336
+ }
337
+ if (store.accounts.length === 1) {
338
+ store.activeEmail = email;
339
+ }
340
+ saveStore(store);
341
+ }
342
+ function getActiveAccountTokens() {
343
+ const store = loadStore();
344
+ if (!store.activeEmail) return null;
345
+ const account = store.accounts.find((a) => a.email === store.activeEmail);
346
+ return account?.tokens || null;
347
+ }
348
+ function setActiveAccount(email) {
349
+ const store = loadStore();
350
+ if (!store.accounts.find((a) => a.email === email)) return false;
351
+ store.activeEmail = email;
352
+ saveStore(store);
353
+ return true;
354
+ }
355
+ function removeAccount(email) {
356
+ const store = loadStore();
357
+ const idx = store.accounts.findIndex((a) => a.email === email);
358
+ if (idx < 0) return false;
359
+ store.accounts.splice(idx, 1);
360
+ if (store.activeEmail === email) {
361
+ store.activeEmail = store.accounts[0]?.email;
362
+ }
363
+ saveStore(store);
364
+ return true;
365
+ }
366
+ function listAccounts() {
367
+ const store = loadStore();
368
+ return store.accounts.map((a) => ({
369
+ email: a.email,
370
+ isActive: a.email === store.activeEmail,
371
+ addedAt: a.addedAt
372
+ }));
373
+ }
374
+ function getAllAccountTokens() {
375
+ const store = loadStore();
376
+ return store.accounts.map((a) => a.tokens);
377
+ }
378
+
379
+ // src/core/errors.ts
380
+ var SourceUnavailableError = class extends Error {
381
+ constructor(source, reason) {
382
+ super(`Source "${source}" unavailable${reason ? `: ${reason}` : ""}`);
383
+ this.name = "SourceUnavailableError";
384
+ }
385
+ };
386
+ var AuthError = class extends Error {
387
+ constructor(message) {
388
+ super(message);
389
+ this.name = "AuthError";
390
+ }
391
+ };
392
+
393
+ // src/sdk/accounts/auth.ts
394
+ import open from "open";
395
+ import http from "http";
396
+ import { URL as URL2 } from "url";
397
+ async function loginAccount() {
398
+ const client = new OAuthClient();
399
+ const authUrl = client.getAuthUrl();
400
+ debug("auth", "Starting OAuth login flow");
401
+ const code = await new Promise((resolve, reject) => {
402
+ const server = http.createServer(async (req, res) => {
403
+ const url = new URL2(req.url || "/", `http://127.0.0.1`);
404
+ const code2 = url.searchParams.get("code");
405
+ if (code2) {
406
+ res.writeHead(200, { "Content-Type": "text/html" });
407
+ res.end(`
408
+ <html><body style="font-family: sans-serif; text-align: center; padding: 50px;">
409
+ <h1>\u2705 Login successful!</h1>
410
+ <p>You can close this tab and return to the terminal.</p>
411
+ </body></html>
412
+ `);
413
+ server.close();
414
+ resolve(code2);
415
+ } else {
416
+ const error = url.searchParams.get("error");
417
+ if (error) {
418
+ res.writeHead(400, { "Content-Type": "text/html" });
419
+ res.end(`<h1>Login failed: ${error}</h1>`);
420
+ server.close();
421
+ reject(new AuthError(`OAuth error: ${error}`));
422
+ } else {
423
+ res.writeHead(404);
424
+ res.end("Waiting for OAuth callback...");
425
+ }
426
+ }
427
+ });
428
+ server.listen(0, "127.0.0.1", () => {
429
+ const addr = server.address();
430
+ if (typeof addr === "object" && addr) {
431
+ debug("auth", `Callback server on port ${addr.port}`);
432
+ open(authUrl).catch(() => {
433
+ console.log(`
434
+ Open this URL in your browser:
435
+
436
+ ${authUrl}
437
+ `);
438
+ });
439
+ }
440
+ });
441
+ setTimeout(() => {
442
+ server.close();
443
+ reject(new AuthError("Login timed out after 5 minutes"));
444
+ }, 5 * 60 * 1e3);
445
+ });
446
+ const tokens = await client.exchangeCode(code);
447
+ const email = tokens.email || "unknown@gmail.com";
448
+ tokens.email = email;
449
+ saveAccountTokens(email, tokens);
450
+ setActiveAccount(email);
451
+ debug("auth", `Logged in as ${email}`);
452
+ return email;
453
+ }
454
+ function getManualLoginUrl() {
455
+ const client = new OAuthClient();
456
+ return client.getAuthUrl();
457
+ }
458
+ async function completeManualLogin(code) {
459
+ const client = new OAuthClient();
460
+ const tokens = await client.exchangeCode(code);
461
+ const email = tokens.email || "unknown@gmail.com";
462
+ tokens.email = email;
463
+ saveAccountTokens(email, tokens);
464
+ setActiveAccount(email);
465
+ return email;
466
+ }
467
+
468
+ export {
469
+ setVerbose,
470
+ debug,
471
+ SourceUnavailableError,
472
+ OAuthClient,
473
+ ensureDirs,
474
+ loadConfig,
475
+ saveConfig,
476
+ getConfigDirPath,
477
+ getDataDirPath,
478
+ getActiveAccountTokens,
479
+ setActiveAccount,
480
+ removeAccount,
481
+ listAccounts,
482
+ getAllAccountTokens,
483
+ loginAccount,
484
+ getManualLoginUrl,
485
+ completeManualLogin
486
+ };
487
+ //# sourceMappingURL=chunk-YZVX5QIP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sources/oauth/client.ts","../src/sources/cloud-code-api.ts","../src/sdk/accounts/storage.ts","../src/core/config.ts","../src/core/logger.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 http from 'http'\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} from '../cloud-code-api.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(): string {\n const params = new URLSearchParams({\n client_id: OAUTH_CLIENT_ID,\n redirect_uri: 'http://127.0.0.1:0/callback',\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): Promise<StoredTokens> {\n const body = new URLSearchParams({\n code,\n client_id: OAUTH_CLIENT_ID,\n client_secret: OAUTH_CLIENT_SECRET,\n redirect_uri: 'http://127.0.0.1:0/callback',\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 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 // ── 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: http.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 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: http.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 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 * 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 'https://www.googleapis.com/auth/cloudcode',\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 } from 'fs'\nimport { join } 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 writeFileSync(getStorePath(), 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 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 * 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 * 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 const authUrl = client.getAuthUrl()\n\n debug('auth', 'Starting OAuth login flow')\n\n // Start a temporary local server to catch the redirect\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' })\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' })\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 // Update redirect URI with actual port\n debug('auth', `Callback server on port ${addr.port}`)\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\n const tokens = await client.exchangeCode(code)\n\n // Get user email\n const email = tokens.email || 'unknown@gmail.com'\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 const email = tokens.email || 'unknown@gmail.com'\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","join","join","existsSync","readFileSync","writeFileSync","URL","code"]}