@kaitranntt/ccs 7.30.1-dev.1 → 7.31.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,16 @@
1
+ /**
2
+ * Shared Authentication Utilities
3
+ *
4
+ * Common functions for OAuth token handling across quota fetchers.
5
+ */
6
+ /**
7
+ * Sanitize email to match CLIProxyAPI auth file naming convention.
8
+ * Replaces @ and . with underscores for filesystem compatibility.
9
+ */
10
+ export declare function sanitizeEmail(email: string): string;
11
+ /**
12
+ * Check if token is expired based on the expired timestamp.
13
+ * Returns false if timestamp is missing or invalid (fail-open for quota display).
14
+ */
15
+ export declare function isTokenExpired(expiredStr?: string): boolean;
16
+ //# sourceMappingURL=auth-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-utils.d.ts","sourceRoot":"","sources":["../../src/cliproxy/auth-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAQ3D"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ /**
3
+ * Shared Authentication Utilities
4
+ *
5
+ * Common functions for OAuth token handling across quota fetchers.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.isTokenExpired = exports.sanitizeEmail = void 0;
9
+ /**
10
+ * Sanitize email to match CLIProxyAPI auth file naming convention.
11
+ * Replaces @ and . with underscores for filesystem compatibility.
12
+ */
13
+ function sanitizeEmail(email) {
14
+ return email.replace(/@/g, '_').replace(/\./g, '_');
15
+ }
16
+ exports.sanitizeEmail = sanitizeEmail;
17
+ /**
18
+ * Check if token is expired based on the expired timestamp.
19
+ * Returns false if timestamp is missing or invalid (fail-open for quota display).
20
+ */
21
+ function isTokenExpired(expiredStr) {
22
+ if (!expiredStr)
23
+ return false;
24
+ try {
25
+ const expiredDate = new Date(expiredStr);
26
+ return expiredDate.getTime() < Date.now();
27
+ }
28
+ catch {
29
+ return false;
30
+ }
31
+ }
32
+ exports.isTokenExpired = isTokenExpired;
33
+ //# sourceMappingURL=auth-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-utils.js","sourceRoot":"","sources":["../../src/cliproxy/auth-utils.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH;;;GAGG;AACH,SAAgB,aAAa,CAAC,KAAa;IACzC,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACtD,CAAC;AAFD,sCAEC;AAED;;;GAGG;AACH,SAAgB,cAAc,CAAC,UAAmB;IAChD,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC;QACzC,OAAO,WAAW,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AARD,wCAQC"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Quota Fetcher for Codex (ChatGPT) Accounts
3
+ *
4
+ * Fetches quota information from ChatGPT backend API.
5
+ * Used for displaying rate limit windows and reset times.
6
+ */
7
+ import type { CodexQuotaResult, CodexQuotaWindow } from './quota-types';
8
+ /** Auth data extracted from Codex auth file */
9
+ interface CodexAuthData {
10
+ accessToken: string;
11
+ accountId: string;
12
+ isExpired: boolean;
13
+ expiresAt: string | null;
14
+ }
15
+ /** Raw API response structure */
16
+ interface CodexUsageResponse {
17
+ plan_type?: string;
18
+ planType?: string;
19
+ rate_limit?: CodexRateLimitWindow;
20
+ rateLimit?: CodexRateLimitWindow;
21
+ code_review_rate_limit?: CodexRateLimitWindow;
22
+ codeReviewRateLimit?: CodexRateLimitWindow;
23
+ }
24
+ /** Rate limit window from API */
25
+ interface CodexRateLimitWindow {
26
+ primary_window?: CodexWindowData;
27
+ primaryWindow?: CodexWindowData;
28
+ secondary_window?: CodexWindowData;
29
+ secondaryWindow?: CodexWindowData;
30
+ }
31
+ /** Individual window data */
32
+ interface CodexWindowData {
33
+ used_percent?: number;
34
+ usedPercent?: number;
35
+ reset_after_seconds?: number | null;
36
+ resetAfterSeconds?: number | null;
37
+ }
38
+ /**
39
+ * Read auth data from Codex auth file
40
+ */
41
+ declare function readCodexAuthData(accountId: string): CodexAuthData | null;
42
+ /**
43
+ * Build CodexQuotaWindow array from API response
44
+ * Handles both snake_case and camelCase field names
45
+ */
46
+ declare function buildCodexQuotaWindows(payload: CodexUsageResponse): CodexQuotaWindow[];
47
+ /**
48
+ * Fetch quota for a single Codex account
49
+ *
50
+ * @param accountId - Account identifier (email)
51
+ * @param verbose - Show detailed diagnostics
52
+ * @returns Quota result with windows and percentages
53
+ */
54
+ export declare function fetchCodexQuota(accountId: string, verbose?: boolean): Promise<CodexQuotaResult>;
55
+ /**
56
+ * Fetch quota for all Codex accounts
57
+ *
58
+ * @param verbose - Show detailed diagnostics
59
+ * @returns Array of account quotas
60
+ */
61
+ export declare function fetchAllCodexQuotas(verbose?: boolean): Promise<{
62
+ account: string;
63
+ quota: CodexQuotaResult;
64
+ }[]>;
65
+ export { readCodexAuthData, buildCodexQuotaWindows };
66
+ //# sourceMappingURL=quota-fetcher-codex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-fetcher-codex.d.ts","sourceRoot":"","sources":["../../src/cliproxy/quota-fetcher-codex.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAWxE,+CAA+C;AAC/C,UAAU,aAAa;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,iCAAiC;AACjC,UAAU,kBAAkB;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,sBAAsB,CAAC,EAAE,oBAAoB,CAAC;IAC9C,mBAAmB,CAAC,EAAE,oBAAoB,CAAC;CAC5C;AAED,iCAAiC;AACjC,UAAU,oBAAoB;IAC5B,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,gBAAgB,CAAC,EAAE,eAAe,CAAC;IACnC,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAED,6BAA6B;AAC7B,UAAU,eAAe;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED;;GAEG;AACH,iBAAS,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAkDlE;AAED;;;GAGG;AACH,iBAAS,sBAAsB,CAAC,OAAO,EAAE,kBAAkB,GAAG,gBAAgB,EAAE,CAmD/E;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,OAAO,UAAQ,GACd,OAAO,CAAC,gBAAgB,CAAC,CAoJ3B;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,UAAQ,GACd,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,EAAE,CAAC,CAezD;AAGD,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,CAAC"}
@@ -0,0 +1,310 @@
1
+ "use strict";
2
+ /**
3
+ * Quota Fetcher for Codex (ChatGPT) Accounts
4
+ *
5
+ * Fetches quota information from ChatGPT backend API.
6
+ * Used for displaying rate limit windows and reset times.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || function (mod) {
25
+ if (mod && mod.__esModule) return mod;
26
+ var result = {};
27
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
28
+ __setModuleDefault(result, mod);
29
+ return result;
30
+ };
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.buildCodexQuotaWindows = exports.readCodexAuthData = exports.fetchAllCodexQuotas = exports.fetchCodexQuota = void 0;
33
+ const fs = __importStar(require("node:fs"));
34
+ const path = __importStar(require("node:path"));
35
+ const config_generator_1 = require("./config-generator");
36
+ const account_manager_1 = require("./account-manager");
37
+ const auth_utils_1 = require("./auth-utils");
38
+ /** ChatGPT backend API base URL */
39
+ const CODEX_API_BASE = 'https://chatgpt.com/backend-api';
40
+ /**
41
+ * User agent matching Codex CLI for API compatibility.
42
+ * Update when Codex CLI releases new versions to maintain compatibility.
43
+ */
44
+ const USER_AGENT = 'codex_cli_rs/0.76.0 (Debian 13.0.0; x86_64) WindowsTerminal';
45
+ /**
46
+ * Read auth data from Codex auth file
47
+ */
48
+ function readCodexAuthData(accountId) {
49
+ const authDirs = [(0, config_generator_1.getAuthDir)(), (0, account_manager_1.getPausedDir)()];
50
+ const sanitizedId = (0, auth_utils_1.sanitizeEmail)(accountId);
51
+ const expectedFile = `codex-${sanitizedId}.json`;
52
+ for (const authDir of authDirs) {
53
+ if (!fs.existsSync(authDir))
54
+ continue;
55
+ const filePath = path.join(authDir, expectedFile);
56
+ if (fs.existsSync(filePath)) {
57
+ try {
58
+ const content = fs.readFileSync(filePath, 'utf-8');
59
+ const data = JSON.parse(content);
60
+ if (!data.access_token)
61
+ continue;
62
+ return {
63
+ accessToken: data.access_token,
64
+ accountId: data.account_id || data.accountId || '',
65
+ isExpired: (0, auth_utils_1.isTokenExpired)(data.expired),
66
+ expiresAt: data.expired || null,
67
+ };
68
+ }
69
+ catch {
70
+ continue;
71
+ }
72
+ }
73
+ // Fallback: scan directory for matching email in file content
74
+ const files = fs.readdirSync(authDir);
75
+ for (const file of files) {
76
+ if (file.startsWith('codex-') && file.endsWith('.json')) {
77
+ const candidatePath = path.join(authDir, file);
78
+ try {
79
+ const content = fs.readFileSync(candidatePath, 'utf-8');
80
+ const data = JSON.parse(content);
81
+ if (data.email === accountId && data.access_token) {
82
+ return {
83
+ accessToken: data.access_token,
84
+ accountId: data.account_id || data.accountId || '',
85
+ isExpired: (0, auth_utils_1.isTokenExpired)(data.expired),
86
+ expiresAt: data.expired || null,
87
+ };
88
+ }
89
+ }
90
+ catch {
91
+ continue;
92
+ }
93
+ }
94
+ }
95
+ }
96
+ return null;
97
+ }
98
+ exports.readCodexAuthData = readCodexAuthData;
99
+ /**
100
+ * Build CodexQuotaWindow array from API response
101
+ * Handles both snake_case and camelCase field names
102
+ */
103
+ function buildCodexQuotaWindows(payload) {
104
+ const windows = [];
105
+ // Get rate limit object (handles both cases)
106
+ const rateLimit = payload.rate_limit || payload.rateLimit;
107
+ const codeReviewRateLimit = payload.code_review_rate_limit || payload.codeReviewRateLimit;
108
+ // Helper to extract window data
109
+ const addWindow = (label, windowData) => {
110
+ if (!windowData)
111
+ return;
112
+ // Clamp usedPercent to [0, 100] range
113
+ const rawUsedPercent = windowData.used_percent ?? windowData.usedPercent ?? 0;
114
+ const usedPercent = Math.max(0, Math.min(100, rawUsedPercent));
115
+ const resetAfterSeconds = windowData.reset_after_seconds ?? windowData.resetAfterSeconds ?? null;
116
+ // Calculate reset timestamp if we have seconds
117
+ let resetAt = null;
118
+ if (resetAfterSeconds !== null && resetAfterSeconds > 0) {
119
+ resetAt = new Date(Date.now() + resetAfterSeconds * 1000).toISOString();
120
+ }
121
+ windows.push({
122
+ label,
123
+ usedPercent,
124
+ remainingPercent: Math.max(0, 100 - usedPercent),
125
+ resetAfterSeconds,
126
+ resetAt,
127
+ });
128
+ };
129
+ // Add main rate limit windows
130
+ if (rateLimit) {
131
+ addWindow('Primary', rateLimit.primary_window || rateLimit.primaryWindow);
132
+ addWindow('Secondary', rateLimit.secondary_window || rateLimit.secondaryWindow);
133
+ }
134
+ // Add code review rate limit windows
135
+ if (codeReviewRateLimit) {
136
+ addWindow('Code Review (Primary)', codeReviewRateLimit.primary_window || codeReviewRateLimit.primaryWindow);
137
+ addWindow('Code Review (Secondary)', codeReviewRateLimit.secondary_window || codeReviewRateLimit.secondaryWindow);
138
+ }
139
+ return windows;
140
+ }
141
+ exports.buildCodexQuotaWindows = buildCodexQuotaWindows;
142
+ /**
143
+ * Fetch quota for a single Codex account
144
+ *
145
+ * @param accountId - Account identifier (email)
146
+ * @param verbose - Show detailed diagnostics
147
+ * @returns Quota result with windows and percentages
148
+ */
149
+ async function fetchCodexQuota(accountId, verbose = false) {
150
+ if (verbose)
151
+ console.error(`[i] Fetching Codex quota for ${accountId}...`);
152
+ const authData = readCodexAuthData(accountId);
153
+ if (!authData) {
154
+ const error = 'Auth file not found for Codex account';
155
+ if (verbose)
156
+ console.error(`[!] Error: ${error}`);
157
+ return {
158
+ success: false,
159
+ windows: [],
160
+ planType: null,
161
+ lastUpdated: Date.now(),
162
+ error,
163
+ accountId,
164
+ };
165
+ }
166
+ if (authData.isExpired) {
167
+ const error = 'Token expired - re-authenticate with ccs cliproxy auth codex';
168
+ if (verbose)
169
+ console.error(`[!] Error: ${error}`);
170
+ return {
171
+ success: false,
172
+ windows: [],
173
+ planType: null,
174
+ lastUpdated: Date.now(),
175
+ error,
176
+ accountId,
177
+ };
178
+ }
179
+ if (!authData.accountId) {
180
+ const error = 'Missing ChatGPT-Account-Id in auth file';
181
+ if (verbose)
182
+ console.error(`[!] Error: ${error}`);
183
+ return {
184
+ success: false,
185
+ windows: [],
186
+ planType: null,
187
+ lastUpdated: Date.now(),
188
+ error,
189
+ accountId,
190
+ };
191
+ }
192
+ const url = `${CODEX_API_BASE}/wham/usage`;
193
+ const controller = new AbortController();
194
+ const timeoutId = setTimeout(() => controller.abort(), 5000);
195
+ try {
196
+ const response = await fetch(url, {
197
+ method: 'GET',
198
+ signal: controller.signal,
199
+ headers: {
200
+ Authorization: `Bearer ${authData.accessToken}`,
201
+ 'ChatGPT-Account-Id': authData.accountId,
202
+ 'User-Agent': USER_AGENT,
203
+ },
204
+ });
205
+ clearTimeout(timeoutId);
206
+ if (verbose)
207
+ console.error(`[i] Codex API status: ${response.status}`);
208
+ if (response.status === 401) {
209
+ return {
210
+ success: false,
211
+ windows: [],
212
+ planType: null,
213
+ lastUpdated: Date.now(),
214
+ error: 'Token expired or invalid',
215
+ accountId,
216
+ };
217
+ }
218
+ if (response.status === 403) {
219
+ return {
220
+ success: false,
221
+ windows: [],
222
+ planType: null,
223
+ lastUpdated: Date.now(),
224
+ error: 'Quota access not available (free plan may not have quota API access)',
225
+ accountId,
226
+ };
227
+ }
228
+ if (response.status === 429) {
229
+ return {
230
+ success: false,
231
+ windows: [],
232
+ planType: null,
233
+ lastUpdated: Date.now(),
234
+ error: 'Rate limited - try again later',
235
+ accountId,
236
+ };
237
+ }
238
+ if (!response.ok) {
239
+ return {
240
+ success: false,
241
+ windows: [],
242
+ planType: null,
243
+ lastUpdated: Date.now(),
244
+ error: `API error: ${response.status}`,
245
+ accountId,
246
+ };
247
+ }
248
+ const data = (await response.json());
249
+ const windows = buildCodexQuotaWindows(data);
250
+ // Extract plan type
251
+ const planTypeRaw = data.plan_type || data.planType;
252
+ let planType = null;
253
+ if (planTypeRaw) {
254
+ const normalized = planTypeRaw.toLowerCase();
255
+ if (normalized === 'free')
256
+ planType = 'free';
257
+ else if (normalized === 'plus')
258
+ planType = 'plus';
259
+ else if (normalized === 'team')
260
+ planType = 'team';
261
+ }
262
+ if (verbose)
263
+ console.error(`[i] Codex windows found: ${windows.length}`);
264
+ return {
265
+ success: true,
266
+ windows,
267
+ planType,
268
+ lastUpdated: Date.now(),
269
+ accountId,
270
+ };
271
+ }
272
+ catch (err) {
273
+ clearTimeout(timeoutId);
274
+ const errorMsg = err instanceof Error && err.name === 'AbortError'
275
+ ? 'Request timeout'
276
+ : err instanceof Error
277
+ ? err.message
278
+ : 'Unknown error';
279
+ if (verbose)
280
+ console.error(`[!] Codex quota error: ${errorMsg}`);
281
+ return {
282
+ success: false,
283
+ windows: [],
284
+ planType: null,
285
+ lastUpdated: Date.now(),
286
+ error: errorMsg,
287
+ accountId,
288
+ };
289
+ }
290
+ }
291
+ exports.fetchCodexQuota = fetchCodexQuota;
292
+ /**
293
+ * Fetch quota for all Codex accounts
294
+ *
295
+ * @param verbose - Show detailed diagnostics
296
+ * @returns Array of account quotas
297
+ */
298
+ async function fetchAllCodexQuotas(verbose = false) {
299
+ const accounts = (0, account_manager_1.getProviderAccounts)('codex');
300
+ if (accounts.length === 0) {
301
+ return [];
302
+ }
303
+ const results = await Promise.all(accounts.map(async (account) => ({
304
+ account: account.id,
305
+ quota: await fetchCodexQuota(account.id, verbose),
306
+ })));
307
+ return results;
308
+ }
309
+ exports.fetchAllCodexQuotas = fetchAllCodexQuotas;
310
+ //# sourceMappingURL=quota-fetcher-codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-fetcher-codex.js","sourceRoot":"","sources":["../../src/cliproxy/quota-fetcher-codex.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,4CAA8B;AAC9B,gDAAkC;AAClC,yDAAgD;AAChD,uDAAsE;AACtE,6CAA6D;AAG7D,mCAAmC;AACnC,MAAM,cAAc,GAAG,iCAAiC,CAAC;AAEzD;;;GAGG;AACH,MAAM,UAAU,GAAG,6DAA6D,CAAC;AAoCjF;;GAEG;AACH,SAAS,iBAAiB,CAAC,SAAiB;IAC1C,MAAM,QAAQ,GAAG,CAAC,IAAA,6BAAU,GAAE,EAAE,IAAA,8BAAY,GAAE,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,IAAA,0BAAa,EAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,SAAS,WAAW,OAAO,CAAC;IAEjD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,SAAS;QAEtC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAClD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACnD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACjC,IAAI,CAAC,IAAI,CAAC,YAAY;oBAAE,SAAS;gBAEjC,OAAO;oBACL,WAAW,EAAE,IAAI,CAAC,YAAY;oBAC9B,SAAS,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,SAAS,IAAI,EAAE;oBAClD,SAAS,EAAE,IAAA,2BAAc,EAAC,IAAI,CAAC,OAAO,CAAC;oBACvC,SAAS,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI;iBAChC,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC;QAED,8DAA8D;QAC9D,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBAC/C,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;oBACxD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;oBACjC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;wBAClD,OAAO;4BACL,WAAW,EAAE,IAAI,CAAC,YAAY;4BAC9B,SAAS,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,SAAS,IAAI,EAAE;4BAClD,SAAS,EAAE,IAAA,2BAAc,EAAC,IAAI,CAAC,OAAO,CAAC;4BACvC,SAAS,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI;yBAChC,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAqPQ,8CAAiB;AAnP1B;;;GAGG;AACH,SAAS,sBAAsB,CAAC,OAA2B;IACzD,MAAM,OAAO,GAAuB,EAAE,CAAC;IAEvC,6CAA6C;IAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC;IAC1D,MAAM,mBAAmB,GAAG,OAAO,CAAC,sBAAsB,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAE1F,gCAAgC;IAChC,MAAM,SAAS,GAAG,CAAC,KAAa,EAAE,UAAuC,EAAQ,EAAE;QACjF,IAAI,CAAC,UAAU;YAAE,OAAO;QAExB,sCAAsC;QACtC,MAAM,cAAc,GAAG,UAAU,CAAC,YAAY,IAAI,UAAU,CAAC,WAAW,IAAI,CAAC,CAAC;QAC9E,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC;QAC/D,MAAM,iBAAiB,GACrB,UAAU,CAAC,mBAAmB,IAAI,UAAU,CAAC,iBAAiB,IAAI,IAAI,CAAC;QAEzE,+CAA+C;QAC/C,IAAI,OAAO,GAAkB,IAAI,CAAC;QAClC,IAAI,iBAAiB,KAAK,IAAI,IAAI,iBAAiB,GAAG,CAAC,EAAE,CAAC;YACxD,OAAO,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,iBAAiB,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1E,CAAC;QAED,OAAO,CAAC,IAAI,CAAC;YACX,KAAK;YACL,WAAW;YACX,gBAAgB,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,WAAW,CAAC;YAChD,iBAAiB;YACjB,OAAO;SACR,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,8BAA8B;IAC9B,IAAI,SAAS,EAAE,CAAC;QACd,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,cAAc,IAAI,SAAS,CAAC,aAAa,CAAC,CAAC;QAC1E,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,gBAAgB,IAAI,SAAS,CAAC,eAAe,CAAC,CAAC;IAClF,CAAC;IAED,qCAAqC;IACrC,IAAI,mBAAmB,EAAE,CAAC;QACxB,SAAS,CACP,uBAAuB,EACvB,mBAAmB,CAAC,cAAc,IAAI,mBAAmB,CAAC,aAAa,CACxE,CAAC;QACF,SAAS,CACP,yBAAyB,EACzB,mBAAmB,CAAC,gBAAgB,IAAI,mBAAmB,CAAC,eAAe,CAC5E,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AA4L2B,wDAAsB;AA1LlD;;;;;;GAMG;AACI,KAAK,UAAU,eAAe,CACnC,SAAiB,EACjB,OAAO,GAAG,KAAK;IAEf,IAAI,OAAO;QAAE,OAAO,CAAC,KAAK,CAAC,gCAAgC,SAAS,KAAK,CAAC,CAAC;IAE3E,MAAM,QAAQ,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,uCAAuC,CAAC;QACtD,IAAI,OAAO;YAAE,OAAO,CAAC,KAAK,CAAC,cAAc,KAAK,EAAE,CAAC,CAAC;QAClD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;YACvB,KAAK;YACL,SAAS;SACV,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,8DAA8D,CAAC;QAC7E,IAAI,OAAO;YAAE,OAAO,CAAC,KAAK,CAAC,cAAc,KAAK,EAAE,CAAC,CAAC;QAClD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;YACvB,KAAK;YACL,SAAS;SACV,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,yCAAyC,CAAC;QACxD,IAAI,OAAO;YAAE,OAAO,CAAC,KAAK,CAAC,cAAc,KAAK,EAAE,CAAC,CAAC;QAClD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;YACvB,KAAK;YACL,SAAS;SACV,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,cAAc,aAAa,CAAC;IAC3C,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC;IAE7D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,QAAQ,CAAC,WAAW,EAAE;gBAC/C,oBAAoB,EAAE,QAAQ,CAAC,SAAS;gBACxC,YAAY,EAAE,UAAU;aACzB;SACF,CAAC,CAAC;QAEH,YAAY,CAAC,SAAS,CAAC,CAAC;QAExB,IAAI,OAAO;YAAE,OAAO,CAAC,KAAK,CAAC,yBAAyB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAEvE,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;gBACvB,KAAK,EAAE,0BAA0B;gBACjC,SAAS;aACV,CAAC;QACJ,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;gBACvB,KAAK,EAAE,sEAAsE;gBAC7E,SAAS;aACV,CAAC;QACJ,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;gBACvB,KAAK,EAAE,gCAAgC;gBACvC,SAAS;aACV,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;gBACvB,KAAK,EAAE,cAAc,QAAQ,CAAC,MAAM,EAAE;gBACtC,SAAS;aACV,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAuB,CAAC;QAC3D,MAAM,OAAO,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAE7C,oBAAoB;QACpB,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC;QACpD,IAAI,QAAQ,GAAoC,IAAI,CAAC;QACrD,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;YAC7C,IAAI,UAAU,KAAK,MAAM;gBAAE,QAAQ,GAAG,MAAM,CAAC;iBACxC,IAAI,UAAU,KAAK,MAAM;gBAAE,QAAQ,GAAG,MAAM,CAAC;iBAC7C,IAAI,UAAU,KAAK,MAAM;gBAAE,QAAQ,GAAG,MAAM,CAAC;QACpD,CAAC;QAED,IAAI,OAAO;YAAE,OAAO,CAAC,KAAK,CAAC,4BAA4B,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAEzE,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO;YACP,QAAQ;YACR,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;YACvB,SAAS;SACV,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,YAAY,CAAC,SAAS,CAAC,CAAC;QACxB,MAAM,QAAQ,GACZ,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY;YAC/C,CAAC,CAAC,iBAAiB;YACnB,CAAC,CAAC,GAAG,YAAY,KAAK;gBACpB,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,eAAe,CAAC;QAExB,IAAI,OAAO;YAAE,OAAO,CAAC,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;QAEjE,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;YACvB,KAAK,EAAE,QAAQ;YACf,SAAS;SACV,CAAC;IACJ,CAAC;AACH,CAAC;AAvJD,0CAuJC;AAED;;;;;GAKG;AACI,KAAK,UAAU,mBAAmB,CACvC,OAAO,GAAG,KAAK;IAEf,MAAM,QAAQ,GAAG,IAAA,qCAAmB,EAAC,OAAO,CAAC,CAAC;IAE9C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QAC/B,OAAO,EAAE,OAAO,CAAC,EAAE;QACnB,KAAK,EAAE,MAAM,eAAe,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC;KAClD,CAAC,CAAC,CACJ,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC;AAjBD,kDAiBC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Quota Fetcher for Gemini CLI Accounts
3
+ *
4
+ * Fetches quota information from Google Cloud Code internal API.
5
+ * Used for displaying bucket-based quotas grouped by model series.
6
+ */
7
+ import type { GeminiCliQuotaResult, GeminiCliBucket } from './quota-types';
8
+ /** Raw bucket from API response */
9
+ interface RawGeminiCliBucket {
10
+ model_id?: string;
11
+ modelId?: string;
12
+ token_type?: string | null;
13
+ tokenType?: string | null;
14
+ remaining_fraction?: number;
15
+ remainingFraction?: number;
16
+ remaining_amount?: number;
17
+ remainingAmount?: number;
18
+ reset_time?: string | null;
19
+ resetTime?: string | null;
20
+ }
21
+ /**
22
+ * Extract project ID from account field
23
+ * Input: "user@example.com (cloudaicompanion-abc-123)"
24
+ * Output: "cloudaicompanion-abc-123"
25
+ */
26
+ declare function resolveGeminiCliProjectId(accountField: string): string | null;
27
+ /**
28
+ * Build GeminiCliBucket array from API response
29
+ * Groups buckets by model series and token type
30
+ */
31
+ declare function buildGeminiCliBuckets(rawBuckets: RawGeminiCliBucket[]): GeminiCliBucket[];
32
+ /**
33
+ * Fetch quota for a single Gemini CLI account
34
+ *
35
+ * @param accountId - Account identifier (email)
36
+ * @param verbose - Show detailed diagnostics
37
+ * @returns Quota result with buckets and percentages
38
+ */
39
+ export declare function fetchGeminiCliQuota(accountId: string, verbose?: boolean): Promise<GeminiCliQuotaResult>;
40
+ /**
41
+ * Fetch quota for all Gemini CLI accounts
42
+ *
43
+ * @param verbose - Show detailed diagnostics
44
+ * @returns Array of account quotas
45
+ */
46
+ export declare function fetchAllGeminiCliQuotas(verbose?: boolean): Promise<{
47
+ account: string;
48
+ quota: GeminiCliQuotaResult;
49
+ }[]>;
50
+ export { resolveGeminiCliProjectId, buildGeminiCliBuckets };
51
+ //# sourceMappingURL=quota-fetcher-gemini-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-fetcher-gemini-cli.d.ts","sourceRoot":"","sources":["../../src/cliproxy/quota-fetcher-gemini-cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAsC3E,mCAAmC;AACnC,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAOD;;;;GAIG;AACH,iBAAS,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQtE;AAmFD;;;GAGG;AACH,iBAAS,qBAAqB,CAAC,UAAU,EAAE,kBAAkB,EAAE,GAAG,eAAe,EAAE,CA4ElF;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,MAAM,EACjB,OAAO,UAAQ,GACd,OAAO,CAAC,oBAAoB,CAAC,CA2I/B;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,UAAQ,GACd,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,EAAE,CAAC,CAe7D;AAGD,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,CAAC"}