@kaitranntt/ccs 7.14.0-dev.1 → 7.14.0-dev.3
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/cliproxy/account-manager.d.ts +46 -1
- package/dist/cliproxy/account-manager.d.ts.map +1 -1
- package/dist/cliproxy/account-manager.js +175 -10
- package/dist/cliproxy/account-manager.js.map +1 -1
- package/dist/cliproxy/auth/oauth-handler.d.ts.map +1 -1
- package/dist/cliproxy/auth/oauth-handler.js +65 -3
- package/dist/cliproxy/auth/oauth-handler.js.map +1 -1
- package/dist/cliproxy/cliproxy-executor.d.ts.map +1 -1
- package/dist/cliproxy/cliproxy-executor.js +12 -23
- package/dist/cliproxy/cliproxy-executor.js.map +1 -1
- package/dist/cliproxy/quota-fetcher.d.ts +3 -1
- package/dist/cliproxy/quota-fetcher.d.ts.map +1 -1
- package/dist/cliproxy/quota-fetcher.js +98 -24
- package/dist/cliproxy/quota-fetcher.js.map +1 -1
- package/dist/cliproxy/quota-manager.d.ts +88 -0
- package/dist/cliproxy/quota-manager.d.ts.map +1 -0
- package/dist/cliproxy/quota-manager.js +278 -0
- package/dist/cliproxy/quota-manager.js.map +1 -0
- package/dist/commands/cliproxy-command.d.ts.map +1 -1
- package/dist/commands/cliproxy-command.js +191 -0
- package/dist/commands/cliproxy-command.js.map +1 -1
- package/dist/commands/help-command.d.ts.map +1 -1
- package/dist/commands/help-command.js +4 -0
- package/dist/commands/help-command.js.map +1 -1
- package/dist/config/unified-config-loader.d.ts.map +1 -1
- package/dist/config/unified-config-loader.js +22 -0
- package/dist/config/unified-config-loader.js.map +1 -1
- package/dist/config/unified-config-types.d.ts +62 -2
- package/dist/config/unified-config-types.d.ts.map +1 -1
- package/dist/config/unified-config-types.js +29 -2
- package/dist/config/unified-config-types.js.map +1 -1
- package/dist/ui/assets/{accounts-wkvC_Z1E.js → accounts-D31DF_DO.js} +1 -1
- package/dist/ui/assets/{alert-dialog--nlDi-Dj.js → alert-dialog-LCg4HaeZ.js} +1 -1
- package/dist/ui/assets/{api-DeyefOLW.js → api-Bmxcet5w.js} +1 -1
- package/dist/ui/assets/{auth-section-BQXfw1cb.js → auth-section-CRTokeZ8.js} +1 -1
- package/dist/ui/assets/{card-P5vPGo2D.js → card-BmnReIPp.js} +1 -1
- package/dist/ui/assets/cliproxy-BrJaxqVj.js +3 -0
- package/dist/ui/assets/{cliproxy-control-panel-Dbs8NAQa.js → cliproxy-control-panel-D7FGe5HL.js} +1 -1
- package/dist/ui/assets/{confirm-dialog-BM75Bkww.js → confirm-dialog-CzpGAyFB.js} +1 -1
- package/dist/ui/assets/{copilot-BwylIlO5.js → copilot-C2v-0P0m.js} +3 -3
- package/dist/ui/assets/{globalenv-section-Cgpz_NQ0.js → globalenv-section-Cx0L1Zte.js} +1 -1
- package/dist/ui/assets/{health-DWUjYWDI.js → health-BvZrzSJ3.js} +1 -1
- package/dist/ui/assets/icons-CZDQWWm2.js +1 -0
- package/dist/ui/assets/index-BX0IVNt5.css +1 -0
- package/dist/ui/assets/{index-CIWe-99u.js → index-CJrvk2Qf.js} +1 -1
- package/dist/ui/assets/{index-D8MFq-UJ.js → index-D8K1YCe7.js} +14 -14
- package/dist/ui/assets/{index-4Wd5fx72.js → index-fED9JOL0.js} +1 -1
- package/dist/ui/assets/{index-f_AuSs01.js → index-qAWtHsB9.js} +1 -1
- package/dist/ui/assets/{shared-I-pAdvVQ.js → shared-Do9VzQ5g.js} +1 -1
- package/dist/ui/assets/{switch-DHwS-NMF.js → switch-CmGBdPfU.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/web-server/index.d.ts.map +1 -1
- package/dist/web-server/index.js +8 -1
- package/dist/web-server/index.js.map +1 -1
- package/dist/web-server/routes/cliproxy-auth-routes.d.ts.map +1 -1
- package/dist/web-server/routes/cliproxy-auth-routes.js +92 -1
- package/dist/web-server/routes/cliproxy-auth-routes.js.map +1 -1
- package/package.json +1 -1
- package/dist/ui/assets/cliproxy-CcMLaKpF.js +0 -3
- package/dist/ui/assets/icons-U9n5DGj9.js +0 -1
- package/dist/ui/assets/index-1g-Hy9VA.css +0 -1
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Quota Manager for Hybrid Auto+Manual Account Selection
|
|
4
|
+
*
|
|
5
|
+
* Provides pre-flight quota checking with caching, tier-based failover,
|
|
6
|
+
* and cooldown tracking for exhausted accounts.
|
|
7
|
+
*
|
|
8
|
+
* Key features:
|
|
9
|
+
* - 30-second in-memory cache for quota results
|
|
10
|
+
* - Tier-priority failover (ultra > pro by default)
|
|
11
|
+
* - Cooldown tracking for exhausted accounts
|
|
12
|
+
* - Respects paused accounts from manual config
|
|
13
|
+
* - Graceful degradation on API failures
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.getQuotaStatus = exports.preflightCheck = exports.findHealthyAccount = exports.clearCooldown = exports.applyCooldown = exports.isOnCooldown = exports.clearQuotaCache = exports.setCachedQuota = exports.getCachedQuota = void 0;
|
|
17
|
+
const quota_fetcher_1 = require("./quota-fetcher");
|
|
18
|
+
const account_manager_1 = require("./account-manager");
|
|
19
|
+
const unified_config_loader_1 = require("../config/unified-config-loader");
|
|
20
|
+
const CACHE_TTL_MS = 30000; // 30 seconds
|
|
21
|
+
const quotaCache = new Map();
|
|
22
|
+
// Request deduplication: track in-flight fetch promises to avoid parallel duplicate requests
|
|
23
|
+
const pendingFetches = new Map();
|
|
24
|
+
function getCacheKey(provider, accountId) {
|
|
25
|
+
return `${provider}:${accountId}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get cached quota result if still valid
|
|
29
|
+
*/
|
|
30
|
+
function getCachedQuota(provider, accountId) {
|
|
31
|
+
const key = getCacheKey(provider, accountId);
|
|
32
|
+
const entry = quotaCache.get(key);
|
|
33
|
+
if (!entry)
|
|
34
|
+
return null;
|
|
35
|
+
if (Date.now() - entry.timestamp > CACHE_TTL_MS) {
|
|
36
|
+
quotaCache.delete(key);
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return entry.result;
|
|
40
|
+
}
|
|
41
|
+
exports.getCachedQuota = getCachedQuota;
|
|
42
|
+
/**
|
|
43
|
+
* Cache quota result
|
|
44
|
+
*/
|
|
45
|
+
function setCachedQuota(provider, accountId, result) {
|
|
46
|
+
const key = getCacheKey(provider, accountId);
|
|
47
|
+
quotaCache.set(key, { result, timestamp: Date.now() });
|
|
48
|
+
}
|
|
49
|
+
exports.setCachedQuota = setCachedQuota;
|
|
50
|
+
/**
|
|
51
|
+
* Clear all cached quota results
|
|
52
|
+
*/
|
|
53
|
+
function clearQuotaCache() {
|
|
54
|
+
quotaCache.clear();
|
|
55
|
+
}
|
|
56
|
+
exports.clearQuotaCache = clearQuotaCache;
|
|
57
|
+
/**
|
|
58
|
+
* Fetch quota with request deduplication
|
|
59
|
+
* If a fetch for this account is already in progress, return the existing promise
|
|
60
|
+
*/
|
|
61
|
+
async function fetchQuotaWithDedup(provider, accountId) {
|
|
62
|
+
const key = getCacheKey(provider, accountId);
|
|
63
|
+
// Check if fetch already in progress
|
|
64
|
+
const pending = pendingFetches.get(key);
|
|
65
|
+
if (pending) {
|
|
66
|
+
return pending;
|
|
67
|
+
}
|
|
68
|
+
// Start new fetch and track it
|
|
69
|
+
const fetchPromise = (0, quota_fetcher_1.fetchAccountQuota)(provider, accountId)
|
|
70
|
+
.then((result) => {
|
|
71
|
+
setCachedQuota(provider, accountId, result);
|
|
72
|
+
return result;
|
|
73
|
+
})
|
|
74
|
+
.catch(() => {
|
|
75
|
+
return { success: false, models: [], lastUpdated: Date.now() };
|
|
76
|
+
})
|
|
77
|
+
.finally(() => {
|
|
78
|
+
pendingFetches.delete(key);
|
|
79
|
+
});
|
|
80
|
+
pendingFetches.set(key, fetchPromise);
|
|
81
|
+
return fetchPromise;
|
|
82
|
+
}
|
|
83
|
+
const cooldownMap = new Map();
|
|
84
|
+
/**
|
|
85
|
+
* Check if account is on cooldown
|
|
86
|
+
*/
|
|
87
|
+
function isOnCooldown(provider, accountId) {
|
|
88
|
+
const key = getCacheKey(provider, accountId);
|
|
89
|
+
const entry = cooldownMap.get(key);
|
|
90
|
+
if (!entry)
|
|
91
|
+
return false;
|
|
92
|
+
if (Date.now() > entry.until) {
|
|
93
|
+
cooldownMap.delete(key);
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
exports.isOnCooldown = isOnCooldown;
|
|
99
|
+
/**
|
|
100
|
+
* Apply cooldown to an exhausted account
|
|
101
|
+
*/
|
|
102
|
+
function applyCooldown(provider, accountId, minutes) {
|
|
103
|
+
const key = getCacheKey(provider, accountId);
|
|
104
|
+
cooldownMap.set(key, { until: Date.now() + minutes * 60 * 1000 });
|
|
105
|
+
}
|
|
106
|
+
exports.applyCooldown = applyCooldown;
|
|
107
|
+
/**
|
|
108
|
+
* Clear cooldown for an account
|
|
109
|
+
*/
|
|
110
|
+
function clearCooldown(provider, accountId) {
|
|
111
|
+
const key = getCacheKey(provider, accountId);
|
|
112
|
+
cooldownMap.delete(key);
|
|
113
|
+
}
|
|
114
|
+
exports.clearCooldown = clearCooldown;
|
|
115
|
+
/**
|
|
116
|
+
* Calculate average quota percentage from models
|
|
117
|
+
*/
|
|
118
|
+
function calculateAverageQuota(quota) {
|
|
119
|
+
if (!quota.success || quota.models.length === 0) {
|
|
120
|
+
return 100; // Assume OK if no data
|
|
121
|
+
}
|
|
122
|
+
const total = quota.models.reduce((sum, m) => sum + m.percentage, 0);
|
|
123
|
+
return total / quota.models.length;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Find healthy account with remaining quota
|
|
127
|
+
* Respects tier priority and skips paused/cooldown accounts
|
|
128
|
+
*/
|
|
129
|
+
async function findHealthyAccount(provider, exclude) {
|
|
130
|
+
const config = (0, unified_config_loader_1.loadOrCreateUnifiedConfig)();
|
|
131
|
+
const tierPriority = config.quota_management?.auto?.tier_priority ?? ['paid'];
|
|
132
|
+
const threshold = config.quota_management?.auto?.exhaustion_threshold ?? 5;
|
|
133
|
+
const accounts = (0, account_manager_1.getProviderAccounts)(provider);
|
|
134
|
+
// Filter available accounts
|
|
135
|
+
const available = accounts.filter((a) => !exclude.includes(a.id) && !(0, account_manager_1.isAccountPaused)(provider, a.id) && !isOnCooldown(provider, a.id));
|
|
136
|
+
if (available.length === 0)
|
|
137
|
+
return null;
|
|
138
|
+
// Fetch quota for each available account (with caching and deduplication)
|
|
139
|
+
const withQuotas = await Promise.all(available.map(async (account) => {
|
|
140
|
+
let quota = getCachedQuota(provider, account.id);
|
|
141
|
+
if (!quota) {
|
|
142
|
+
quota = await fetchQuotaWithDedup(provider, account.id);
|
|
143
|
+
}
|
|
144
|
+
const avgQuota = calculateAverageQuota(quota);
|
|
145
|
+
return {
|
|
146
|
+
id: account.id,
|
|
147
|
+
tier: account.tier || 'paid',
|
|
148
|
+
lastQuota: avgQuota,
|
|
149
|
+
};
|
|
150
|
+
}));
|
|
151
|
+
// Filter by threshold
|
|
152
|
+
const healthy = withQuotas.filter((a) => a.lastQuota >= threshold);
|
|
153
|
+
if (healthy.length === 0)
|
|
154
|
+
return null;
|
|
155
|
+
// Sort by tier priority then quota descending
|
|
156
|
+
healthy.sort((a, b) => {
|
|
157
|
+
const tierA = tierPriority.indexOf(a.tier);
|
|
158
|
+
const tierB = tierPriority.indexOf(b.tier);
|
|
159
|
+
const tierOrderA = tierA === -1 ? 999 : tierA;
|
|
160
|
+
const tierOrderB = tierB === -1 ? 999 : tierB;
|
|
161
|
+
if (tierOrderA !== tierOrderB)
|
|
162
|
+
return tierOrderA - tierOrderB;
|
|
163
|
+
return b.lastQuota - a.lastQuota;
|
|
164
|
+
});
|
|
165
|
+
return healthy[0];
|
|
166
|
+
}
|
|
167
|
+
exports.findHealthyAccount = findHealthyAccount;
|
|
168
|
+
/**
|
|
169
|
+
* Find and switch to a healthy account
|
|
170
|
+
*/
|
|
171
|
+
async function findAndSwitch(provider, excludeAccountId, reason) {
|
|
172
|
+
const alternative = await findHealthyAccount(provider, [excludeAccountId]);
|
|
173
|
+
if (!alternative) {
|
|
174
|
+
// No alternatives: use original anyway (graceful degradation)
|
|
175
|
+
return {
|
|
176
|
+
proceed: true,
|
|
177
|
+
accountId: excludeAccountId,
|
|
178
|
+
reason: `${reason}, no alternatives available`,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
// Switch default
|
|
182
|
+
(0, account_manager_1.setDefaultAccount)(provider, alternative.id);
|
|
183
|
+
(0, account_manager_1.touchAccount)(provider, alternative.id);
|
|
184
|
+
return {
|
|
185
|
+
proceed: true,
|
|
186
|
+
accountId: alternative.id,
|
|
187
|
+
switchedFrom: excludeAccountId,
|
|
188
|
+
reason,
|
|
189
|
+
quotaPercent: alternative.lastQuota,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Perform pre-flight quota check before session start
|
|
194
|
+
*
|
|
195
|
+
* Checks if default account has sufficient quota, auto-switches if needed.
|
|
196
|
+
* Respects paused accounts, tier priority, and cooldown settings.
|
|
197
|
+
*
|
|
198
|
+
* @param provider - CLIProxy provider (only 'agy' supports quota)
|
|
199
|
+
* @returns PreflightResult with account to use and any switch info
|
|
200
|
+
*/
|
|
201
|
+
async function preflightCheck(provider) {
|
|
202
|
+
// Only Antigravity supports quota checking
|
|
203
|
+
if (provider !== 'agy') {
|
|
204
|
+
const defaultAccount = (0, account_manager_1.getDefaultAccount)(provider);
|
|
205
|
+
return { proceed: true, accountId: defaultAccount?.id || '' };
|
|
206
|
+
}
|
|
207
|
+
const config = (0, unified_config_loader_1.loadOrCreateUnifiedConfig)();
|
|
208
|
+
const quotaConfig = config.quota_management;
|
|
209
|
+
// Skip if preflight disabled or mode is manual
|
|
210
|
+
if (!quotaConfig?.auto?.preflight_check || quotaConfig?.mode === 'manual') {
|
|
211
|
+
const defaultAccount = (0, account_manager_1.getDefaultAccount)(provider);
|
|
212
|
+
return { proceed: true, accountId: defaultAccount?.id || '' };
|
|
213
|
+
}
|
|
214
|
+
const defaultAccount = (0, account_manager_1.getDefaultAccount)(provider);
|
|
215
|
+
if (!defaultAccount) {
|
|
216
|
+
return { proceed: false, accountId: '', reason: 'No accounts configured' };
|
|
217
|
+
}
|
|
218
|
+
// Check forced_default override (manual mode)
|
|
219
|
+
const forcedDefault = quotaConfig.manual?.forced_default;
|
|
220
|
+
if (forcedDefault) {
|
|
221
|
+
const forcedAccount = (0, account_manager_1.getProviderAccounts)(provider).find((a) => a.id === forcedDefault);
|
|
222
|
+
if (forcedAccount) {
|
|
223
|
+
return { proceed: true, accountId: forcedAccount.id, reason: 'Forced default override' };
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// Check if default is paused
|
|
227
|
+
if ((0, account_manager_1.isAccountPaused)(provider, defaultAccount.id)) {
|
|
228
|
+
return await findAndSwitch(provider, defaultAccount.id, 'Default account is paused');
|
|
229
|
+
}
|
|
230
|
+
// Check cooldown
|
|
231
|
+
if (isOnCooldown(provider, defaultAccount.id)) {
|
|
232
|
+
return await findAndSwitch(provider, defaultAccount.id, 'Default account on cooldown');
|
|
233
|
+
}
|
|
234
|
+
// Check quota (with cache and deduplication)
|
|
235
|
+
let quota = getCachedQuota(provider, defaultAccount.id);
|
|
236
|
+
if (!quota) {
|
|
237
|
+
quota = await fetchQuotaWithDedup(provider, defaultAccount.id);
|
|
238
|
+
}
|
|
239
|
+
// Calculate average quota
|
|
240
|
+
const avgQuota = calculateAverageQuota(quota);
|
|
241
|
+
const threshold = quotaConfig.auto?.exhaustion_threshold ?? 5;
|
|
242
|
+
if (avgQuota < threshold) {
|
|
243
|
+
// Apply cooldown to exhausted account
|
|
244
|
+
applyCooldown(provider, defaultAccount.id, quotaConfig.auto?.cooldown_minutes ?? 5);
|
|
245
|
+
return await findAndSwitch(provider, defaultAccount.id, `Quota exhausted (${avgQuota.toFixed(1)}%)`);
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
proceed: true,
|
|
249
|
+
accountId: defaultAccount.id,
|
|
250
|
+
quotaPercent: avgQuota,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
exports.preflightCheck = preflightCheck;
|
|
254
|
+
/**
|
|
255
|
+
* Get quota status for all accounts of a provider
|
|
256
|
+
* Used by CLI status command
|
|
257
|
+
*/
|
|
258
|
+
async function getQuotaStatus(provider) {
|
|
259
|
+
const accounts = (0, account_manager_1.getProviderAccounts)(provider);
|
|
260
|
+
const defaultAccount = (0, account_manager_1.getDefaultAccount)(provider);
|
|
261
|
+
const results = await Promise.all(accounts.map(async (account) => {
|
|
262
|
+
let quota = getCachedQuota(provider, account.id);
|
|
263
|
+
if (!quota && provider === 'agy') {
|
|
264
|
+
quota = await fetchQuotaWithDedup(provider, account.id);
|
|
265
|
+
}
|
|
266
|
+
const avgQuota = quota ? calculateAverageQuota(quota) : 100;
|
|
267
|
+
return {
|
|
268
|
+
account,
|
|
269
|
+
quota: avgQuota,
|
|
270
|
+
paused: (0, account_manager_1.isAccountPaused)(provider, account.id),
|
|
271
|
+
onCooldown: isOnCooldown(provider, account.id),
|
|
272
|
+
isDefault: defaultAccount?.id === account.id,
|
|
273
|
+
};
|
|
274
|
+
}));
|
|
275
|
+
return { accounts: results };
|
|
276
|
+
}
|
|
277
|
+
exports.getQuotaStatus = getQuotaStatus;
|
|
278
|
+
//# sourceMappingURL=quota-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quota-manager.js","sourceRoot":"","sources":["../../src/cliproxy/quota-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cliproxy-command.d.ts","sourceRoot":"","sources":["../../src/commands/cliproxy-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;
|
|
1
|
+
{"version":3,"file":"cliproxy-command.d.ts","sourceRoot":"","sources":["../../src/commands/cliproxy-command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AA23BH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiFzE"}
|
|
@@ -47,6 +47,7 @@ const path = __importStar(require("path"));
|
|
|
47
47
|
const auth_handler_1 = require("../cliproxy/auth-handler");
|
|
48
48
|
const account_manager_1 = require("../cliproxy/account-manager");
|
|
49
49
|
const quota_fetcher_1 = require("../cliproxy/quota-fetcher");
|
|
50
|
+
const quota_manager_1 = require("../cliproxy/quota-manager");
|
|
50
51
|
const platform_detector_1 = require("../cliproxy/platform-detector");
|
|
51
52
|
const profile_detector_1 = require("../auth/profile-detector");
|
|
52
53
|
const model_catalog_1 = require("../cliproxy/model-catalog");
|
|
@@ -478,6 +479,15 @@ async function showHelp() {
|
|
|
478
479
|
['remove <name>', 'Remove a CLIProxy variant profile'],
|
|
479
480
|
],
|
|
480
481
|
],
|
|
482
|
+
[
|
|
483
|
+
'Quota Management:',
|
|
484
|
+
[
|
|
485
|
+
['default <account>', 'Set default account for rotation'],
|
|
486
|
+
['pause <account>', 'Pause account (skip in rotation)'],
|
|
487
|
+
['resume <account>', 'Resume paused account'],
|
|
488
|
+
['quota', 'Show quota status for all accounts'],
|
|
489
|
+
],
|
|
490
|
+
],
|
|
481
491
|
[
|
|
482
492
|
'Proxy Lifecycle:',
|
|
483
493
|
[
|
|
@@ -598,6 +608,170 @@ function formatQuotaBar(percentage) {
|
|
|
598
608
|
return `[${filledChar.repeat(filled)}${' '.repeat(empty)}]`;
|
|
599
609
|
}
|
|
600
610
|
// ============================================================================
|
|
611
|
+
// QUOTA MANAGEMENT COMMANDS
|
|
612
|
+
// ============================================================================
|
|
613
|
+
async function handleSetDefault(args) {
|
|
614
|
+
await (0, ui_1.initUI)();
|
|
615
|
+
const parsed = parseProfileArgs(args);
|
|
616
|
+
if (!parsed.name) {
|
|
617
|
+
console.log((0, ui_1.fail)('Usage: ccs cliproxy default <account> [--provider <provider>]'));
|
|
618
|
+
console.log('');
|
|
619
|
+
console.log('Examples:');
|
|
620
|
+
console.log(' ccs cliproxy default ultra@gmail.com');
|
|
621
|
+
console.log(' ccs cliproxy default john --provider agy');
|
|
622
|
+
process.exit(1);
|
|
623
|
+
}
|
|
624
|
+
const provider = (parsed.provider || 'agy');
|
|
625
|
+
const account = (0, account_manager_1.findAccountByQuery)(provider, parsed.name);
|
|
626
|
+
if (!account) {
|
|
627
|
+
console.log((0, ui_1.fail)(`Account not found: ${parsed.name}`));
|
|
628
|
+
console.log('');
|
|
629
|
+
const accounts = (0, account_manager_1.getProviderAccounts)(provider);
|
|
630
|
+
if (accounts.length > 0) {
|
|
631
|
+
console.log('Available accounts:');
|
|
632
|
+
for (const acc of accounts) {
|
|
633
|
+
const badge = acc.isDefault ? (0, ui_1.color)(' (current default)', 'info') : '';
|
|
634
|
+
console.log(` - ${acc.email || acc.id}${badge}`);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
console.log(`No accounts found for provider: ${provider}`);
|
|
639
|
+
console.log(`Run: ccs ${provider} --auth`);
|
|
640
|
+
}
|
|
641
|
+
process.exit(1);
|
|
642
|
+
}
|
|
643
|
+
const success = (0, account_manager_1.setDefaultAccount)(provider, account.id);
|
|
644
|
+
if (success) {
|
|
645
|
+
console.log((0, ui_1.ok)(`Default account set to: ${account.email || account.id}`));
|
|
646
|
+
console.log((0, ui_1.info)(`Provider: ${provider}`));
|
|
647
|
+
}
|
|
648
|
+
else {
|
|
649
|
+
console.log((0, ui_1.fail)('Failed to set default account'));
|
|
650
|
+
process.exit(1);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
async function handlePauseAccount(args) {
|
|
654
|
+
await (0, ui_1.initUI)();
|
|
655
|
+
const parsed = parseProfileArgs(args);
|
|
656
|
+
if (!parsed.name) {
|
|
657
|
+
console.log((0, ui_1.fail)('Usage: ccs cliproxy pause <account> [--provider <provider>]'));
|
|
658
|
+
console.log('');
|
|
659
|
+
console.log('Pauses an account so it will be skipped in quota rotation.');
|
|
660
|
+
process.exit(1);
|
|
661
|
+
}
|
|
662
|
+
const provider = (parsed.provider || 'agy');
|
|
663
|
+
const account = (0, account_manager_1.findAccountByQuery)(provider, parsed.name);
|
|
664
|
+
if (!account) {
|
|
665
|
+
console.log((0, ui_1.fail)(`Account not found: ${parsed.name}`));
|
|
666
|
+
process.exit(1);
|
|
667
|
+
}
|
|
668
|
+
if (account.paused) {
|
|
669
|
+
console.log((0, ui_1.warn)(`Account already paused: ${account.email || account.id}`));
|
|
670
|
+
console.log((0, ui_1.info)(`Paused at: ${account.pausedAt || 'unknown'}`));
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
const success = (0, account_manager_1.pauseAccount)(provider, account.id);
|
|
674
|
+
if (success) {
|
|
675
|
+
console.log((0, ui_1.ok)(`Account paused: ${account.email || account.id}`));
|
|
676
|
+
console.log((0, ui_1.info)('Account will be skipped in quota rotation'));
|
|
677
|
+
}
|
|
678
|
+
else {
|
|
679
|
+
console.log((0, ui_1.fail)('Failed to pause account'));
|
|
680
|
+
process.exit(1);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
async function handleResumeAccount(args) {
|
|
684
|
+
await (0, ui_1.initUI)();
|
|
685
|
+
const parsed = parseProfileArgs(args);
|
|
686
|
+
if (!parsed.name) {
|
|
687
|
+
console.log((0, ui_1.fail)('Usage: ccs cliproxy resume <account> [--provider <provider>]'));
|
|
688
|
+
console.log('');
|
|
689
|
+
console.log('Resumes a paused account for quota rotation.');
|
|
690
|
+
process.exit(1);
|
|
691
|
+
}
|
|
692
|
+
const provider = (parsed.provider || 'agy');
|
|
693
|
+
const account = (0, account_manager_1.findAccountByQuery)(provider, parsed.name);
|
|
694
|
+
if (!account) {
|
|
695
|
+
console.log((0, ui_1.fail)(`Account not found: ${parsed.name}`));
|
|
696
|
+
process.exit(1);
|
|
697
|
+
}
|
|
698
|
+
if (!account.paused) {
|
|
699
|
+
console.log((0, ui_1.warn)(`Account is not paused: ${account.email || account.id}`));
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
const success = (0, account_manager_1.resumeAccount)(provider, account.id);
|
|
703
|
+
if (success) {
|
|
704
|
+
console.log((0, ui_1.ok)(`Account resumed: ${account.email || account.id}`));
|
|
705
|
+
console.log((0, ui_1.info)('Account is now active in quota rotation'));
|
|
706
|
+
}
|
|
707
|
+
else {
|
|
708
|
+
console.log((0, ui_1.fail)('Failed to resume account'));
|
|
709
|
+
process.exit(1);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
async function handleQuotaStatus() {
|
|
713
|
+
await (0, ui_1.initUI)();
|
|
714
|
+
console.log((0, ui_1.header)('Quota Status'));
|
|
715
|
+
console.log('');
|
|
716
|
+
const provider = 'agy';
|
|
717
|
+
const accounts = (0, account_manager_1.getProviderAccounts)(provider);
|
|
718
|
+
if (accounts.length === 0) {
|
|
719
|
+
console.log((0, ui_1.info)('No Antigravity accounts configured'));
|
|
720
|
+
console.log(` Run: ${(0, ui_1.color)('ccs agy --auth', 'command')} to authenticate`);
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
console.log((0, ui_1.dim)('Fetching quotas...'));
|
|
724
|
+
const quotaResult = await (0, quota_fetcher_1.fetchAllProviderQuotas)(provider);
|
|
725
|
+
// Build table rows
|
|
726
|
+
const rows = [];
|
|
727
|
+
for (const account of accounts) {
|
|
728
|
+
const quotaData = quotaResult.accounts.find((q) => q.account.id === account.id);
|
|
729
|
+
const quota = quotaData?.quota;
|
|
730
|
+
// Calculate average quota
|
|
731
|
+
let avgQuota = 'N/A';
|
|
732
|
+
if (quota?.success && quota.models.length > 0) {
|
|
733
|
+
const avg = Math.round(quota.models.reduce((sum, m) => sum + m.percentage, 0) / quota.models.length);
|
|
734
|
+
avgQuota = `${avg}%`;
|
|
735
|
+
}
|
|
736
|
+
// Build status badges
|
|
737
|
+
const statusParts = [];
|
|
738
|
+
if (account.paused)
|
|
739
|
+
statusParts.push((0, ui_1.color)('PAUSED', 'warning'));
|
|
740
|
+
if ((0, quota_manager_1.isOnCooldown)(provider, account.id))
|
|
741
|
+
statusParts.push((0, ui_1.color)('COOLDOWN', 'warning'));
|
|
742
|
+
const defaultMark = account.isDefault ? (0, ui_1.color)('*', 'success') : ' ';
|
|
743
|
+
const tier = account.tier || 'unknown';
|
|
744
|
+
const status = statusParts.join(', ');
|
|
745
|
+
rows.push([
|
|
746
|
+
defaultMark,
|
|
747
|
+
account.nickname || account.email || account.id,
|
|
748
|
+
tier,
|
|
749
|
+
avgQuota,
|
|
750
|
+
status,
|
|
751
|
+
]);
|
|
752
|
+
}
|
|
753
|
+
console.log('');
|
|
754
|
+
console.log((0, ui_1.table)(rows, {
|
|
755
|
+
head: ['', 'Account', 'Tier', 'Quota', 'Status'],
|
|
756
|
+
colWidths: [3, 30, 10, 10, 20],
|
|
757
|
+
}));
|
|
758
|
+
console.log('');
|
|
759
|
+
console.log((0, ui_1.info)(`Default account marked with ${(0, ui_1.color)('*', 'success')}`));
|
|
760
|
+
console.log('');
|
|
761
|
+
// Show summary of paused/cooldown accounts
|
|
762
|
+
const pausedCount = accounts.filter((a) => a.paused).length;
|
|
763
|
+
const cooldownCount = accounts.filter((a) => (0, quota_manager_1.isOnCooldown)(provider, a.id)).length;
|
|
764
|
+
if (pausedCount > 0) {
|
|
765
|
+
console.log((0, ui_1.warn)(`${pausedCount} account(s) paused - use 'ccs cliproxy resume <account>' to re-enable`));
|
|
766
|
+
}
|
|
767
|
+
if (cooldownCount > 0) {
|
|
768
|
+
console.log((0, ui_1.info)(`${cooldownCount} account(s) on cooldown (exhausted recently)`));
|
|
769
|
+
}
|
|
770
|
+
if (pausedCount > 0 || cooldownCount > 0) {
|
|
771
|
+
console.log('');
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
// ============================================================================
|
|
601
775
|
// MAIN ROUTER
|
|
602
776
|
// ============================================================================
|
|
603
777
|
async function handleCliproxyCommand(args) {
|
|
@@ -631,6 +805,23 @@ async function handleCliproxyCommand(args) {
|
|
|
631
805
|
await handleDoctor();
|
|
632
806
|
return;
|
|
633
807
|
}
|
|
808
|
+
// Quota management commands
|
|
809
|
+
if (command === 'default') {
|
|
810
|
+
await handleSetDefault(args.slice(1));
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
if (command === 'pause') {
|
|
814
|
+
await handlePauseAccount(args.slice(1));
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
if (command === 'resume') {
|
|
818
|
+
await handleResumeAccount(args.slice(1));
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
if (command === 'quota') {
|
|
822
|
+
await handleQuotaStatus();
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
634
825
|
const installIdx = args.indexOf('--install');
|
|
635
826
|
if (installIdx !== -1) {
|
|
636
827
|
let version = args[installIdx + 1];
|