opencode-quotas 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +344 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +42 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/constants.d.ts +9 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +15 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/defaults.d.ts +3 -0
- package/dist/src/defaults.d.ts.map +1 -0
- package/dist/src/defaults.js +52 -0
- package/dist/src/defaults.js.map +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +265 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces.d.ts +197 -0
- package/dist/src/interfaces.d.ts.map +1 -0
- package/dist/src/interfaces.js +2 -0
- package/dist/src/interfaces.js.map +1 -0
- package/dist/src/logger.d.ts +14 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +44 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/plugin-state.d.ts +20 -0
- package/dist/src/plugin-state.d.ts.map +1 -0
- package/dist/src/plugin-state.js +53 -0
- package/dist/src/plugin-state.js.map +1 -0
- package/dist/src/providers/antigravity/auth.d.ts +12 -0
- package/dist/src/providers/antigravity/auth.d.ts.map +1 -0
- package/dist/src/providers/antigravity/auth.js +109 -0
- package/dist/src/providers/antigravity/auth.js.map +1 -0
- package/dist/src/providers/antigravity/index.d.ts +2 -0
- package/dist/src/providers/antigravity/index.d.ts.map +1 -0
- package/dist/src/providers/antigravity/index.js +2 -0
- package/dist/src/providers/antigravity/index.js.map +1 -0
- package/dist/src/providers/antigravity/provider.d.ts +34 -0
- package/dist/src/providers/antigravity/provider.d.ts.map +1 -0
- package/dist/src/providers/antigravity/provider.js +216 -0
- package/dist/src/providers/antigravity/provider.js.map +1 -0
- package/dist/src/providers/codex.d.ts +4 -0
- package/dist/src/providers/codex.d.ts.map +1 -0
- package/dist/src/providers/codex.js +242 -0
- package/dist/src/providers/codex.js.map +1 -0
- package/dist/src/providers/github.d.ts +4 -0
- package/dist/src/providers/github.d.ts.map +1 -0
- package/dist/src/providers/github.js +139 -0
- package/dist/src/providers/github.js.map +1 -0
- package/dist/src/quota-cache.d.ts +26 -0
- package/dist/src/quota-cache.d.ts.map +1 -0
- package/dist/src/quota-cache.js +107 -0
- package/dist/src/quota-cache.js.map +1 -0
- package/dist/src/registry.d.ts +3 -0
- package/dist/src/registry.d.ts.map +1 -0
- package/dist/src/registry.js +23 -0
- package/dist/src/registry.js.map +1 -0
- package/dist/src/services/aggregation-service.d.ts +34 -0
- package/dist/src/services/aggregation-service.d.ts.map +1 -0
- package/dist/src/services/aggregation-service.js +89 -0
- package/dist/src/services/aggregation-service.js.map +1 -0
- package/dist/src/services/config-loader.d.ts +25 -0
- package/dist/src/services/config-loader.d.ts.map +1 -0
- package/dist/src/services/config-loader.js +105 -0
- package/dist/src/services/config-loader.js.map +1 -0
- package/dist/src/services/history-service.d.ts +15 -0
- package/dist/src/services/history-service.d.ts.map +1 -0
- package/dist/src/services/history-service.js +99 -0
- package/dist/src/services/history-service.js.map +1 -0
- package/dist/src/services/prediction-engine.d.ts +47 -0
- package/dist/src/services/prediction-engine.d.ts.map +1 -0
- package/dist/src/services/prediction-engine.js +94 -0
- package/dist/src/services/prediction-engine.js.map +1 -0
- package/dist/src/services/quota-service.d.ts +41 -0
- package/dist/src/services/quota-service.d.ts.map +1 -0
- package/dist/src/services/quota-service.js +257 -0
- package/dist/src/services/quota-service.js.map +1 -0
- package/dist/src/tools/quotas.d.ts +11 -0
- package/dist/src/tools/quotas.d.ts.map +1 -0
- package/dist/src/tools/quotas.js +62 -0
- package/dist/src/tools/quotas.js.map +1 -0
- package/dist/src/ui/progress-bar.d.ts +20 -0
- package/dist/src/ui/progress-bar.d.ts.map +1 -0
- package/dist/src/ui/progress-bar.js +150 -0
- package/dist/src/ui/progress-bar.js.map +1 -0
- package/dist/src/ui/quota-table.d.ts +15 -0
- package/dist/src/ui/quota-table.d.ts.map +1 -0
- package/dist/src/ui/quota-table.js +136 -0
- package/dist/src/ui/quota-table.js.map +1 -0
- package/dist/src/utils/debug.d.ts +1 -0
- package/dist/src/utils/debug.d.ts.map +1 -0
- package/dist/src/utils/debug.js +3 -0
- package/dist/src/utils/debug.js.map +1 -0
- package/dist/src/utils/paths.d.ts +7 -0
- package/dist/src/utils/paths.d.ts.map +1 -0
- package/dist/src/utils/paths.js +37 -0
- package/dist/src/utils/paths.js.map +1 -0
- package/dist/src/utils/time.d.ts +3 -0
- package/dist/src/utils/time.d.ts.map +1 -0
- package/dist/src/utils/time.js +38 -0
- package/dist/src/utils/time.js.map +1 -0
- package/dist/src/utils/validation.d.ts +6 -0
- package/dist/src/utils/validation.d.ts.map +1 -0
- package/dist/src/utils/validation.js +66 -0
- package/dist/src/utils/validation.js.map +1 -0
- package/package.json +42 -0
- package/src/cli.ts +53 -0
- package/src/constants.ts +17 -0
- package/src/defaults.ts +53 -0
- package/src/index.ts +338 -0
- package/src/interfaces.ts +258 -0
- package/src/logger.ts +55 -0
- package/src/plugin-state.ts +65 -0
- package/src/providers/antigravity/auth.ts +163 -0
- package/src/providers/antigravity/index.ts +1 -0
- package/src/providers/antigravity/provider.ts +337 -0
- package/src/providers/codex.ts +327 -0
- package/src/providers/github.ts +161 -0
- package/src/quota-cache.ts +157 -0
- package/src/registry.ts +30 -0
- package/src/services/aggregation-service.ts +116 -0
- package/src/services/config-loader.ts +124 -0
- package/src/services/history-service.ts +116 -0
- package/src/services/prediction-engine.ts +133 -0
- package/src/services/quota-service.ts +343 -0
- package/src/tools/quotas.ts +78 -0
- package/src/ui/progress-bar.ts +204 -0
- package/src/ui/quota-table.ts +173 -0
- package/src/utils/debug.ts +1 -0
- package/src/utils/paths.ts +41 -0
- package/src/utils/time.ts +40 -0
- package/src/utils/validation.ts +63 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { ANTIGRAVITY_ACCOUNTS_FILE } from "../../utils/paths";
|
|
3
|
+
/**
|
|
4
|
+
* PUBLIC OAUTH CREDENTIALS - INTENTIONALLY COMMITTED
|
|
5
|
+
*
|
|
6
|
+
* These are "Installed Application" credentials for Google's Native App OAuth flow.
|
|
7
|
+
* Per Google's documentation, the client_secret for native applications is NOT
|
|
8
|
+
* considered confidential. Security relies solely on the user's refresh_token
|
|
9
|
+
* stored locally in ~/.config/opencode/antigravity-accounts.json.
|
|
10
|
+
*
|
|
11
|
+
* See: https://developers.google.com/identity/protocols/oauth2/native-app
|
|
12
|
+
*/
|
|
13
|
+
const ANTIGRAVITY_CLIENT_ID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com"; // gitleaks:allow
|
|
14
|
+
const ANTIGRAVITY_CLIENT_SECRET = "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"; // gitleaks:allow
|
|
15
|
+
const TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
16
|
+
let cachedCredential = null;
|
|
17
|
+
function getAccountsFilePath() {
|
|
18
|
+
return ANTIGRAVITY_ACCOUNTS_FILE();
|
|
19
|
+
}
|
|
20
|
+
async function loadAccounts() {
|
|
21
|
+
const accountsPath = getAccountsFilePath();
|
|
22
|
+
try {
|
|
23
|
+
const content = await readFile(accountsPath, "utf-8");
|
|
24
|
+
const data = JSON.parse(content);
|
|
25
|
+
if (!data.accounts || data.accounts.length === 0) {
|
|
26
|
+
throw new Error("No accounts found in antigravity-accounts.json");
|
|
27
|
+
}
|
|
28
|
+
return data;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error.code === "ENOENT") {
|
|
32
|
+
throw new Error("Antigravity accounts file not found.\n" +
|
|
33
|
+
"Run 'opencode auth login' first to authenticate with Google.");
|
|
34
|
+
}
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export async function hasCloudCredentials() {
|
|
39
|
+
try {
|
|
40
|
+
await loadAccounts();
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function refreshAccessToken(refreshToken) {
|
|
48
|
+
const response = await fetch(TOKEN_URL, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: {
|
|
51
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
52
|
+
},
|
|
53
|
+
body: new URLSearchParams({
|
|
54
|
+
client_id: ANTIGRAVITY_CLIENT_ID,
|
|
55
|
+
client_secret: ANTIGRAVITY_CLIENT_SECRET,
|
|
56
|
+
refresh_token: refreshToken,
|
|
57
|
+
grant_type: "refresh_token",
|
|
58
|
+
}).toString(),
|
|
59
|
+
});
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
const errorText = await response.text();
|
|
62
|
+
if (errorText.toLowerCase().includes("invalid_grant")) {
|
|
63
|
+
throw new Error("Refresh token is invalid or expired. Run 'opencode auth login' to re-authenticate.");
|
|
64
|
+
}
|
|
65
|
+
throw new Error(`Token refresh failed: ${response.status} - ${errorText}`);
|
|
66
|
+
}
|
|
67
|
+
const data = (await response.json());
|
|
68
|
+
return {
|
|
69
|
+
accessToken: data.access_token,
|
|
70
|
+
expiresAt: Date.now() + data.expires_in * 1000,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
export async function getCloudCredentials() {
|
|
74
|
+
const accountsFile = await loadAccounts();
|
|
75
|
+
const activeAccount = accountsFile.accounts[accountsFile.activeIndex] ?? accountsFile.accounts[0];
|
|
76
|
+
if (!activeAccount) {
|
|
77
|
+
throw new Error("No active account found in antigravity-accounts.json");
|
|
78
|
+
}
|
|
79
|
+
// Check cache (5 min buffer)
|
|
80
|
+
const fiveMinutesInMs = 5 * 60 * 1000;
|
|
81
|
+
if (cachedCredential &&
|
|
82
|
+
cachedCredential.email === activeAccount.email &&
|
|
83
|
+
cachedCredential.expiresAt > Date.now() + fiveMinutesInMs) {
|
|
84
|
+
return {
|
|
85
|
+
accessToken: cachedCredential.accessToken,
|
|
86
|
+
projectId: cachedCredential.projectId,
|
|
87
|
+
email: cachedCredential.email,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const { accessToken, expiresAt } = await refreshAccessToken(activeAccount.refreshToken);
|
|
91
|
+
cachedCredential = {
|
|
92
|
+
accessToken,
|
|
93
|
+
projectId: activeAccount.projectId,
|
|
94
|
+
email: activeAccount.email,
|
|
95
|
+
expiresAt,
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
accessToken,
|
|
99
|
+
projectId: activeAccount.projectId,
|
|
100
|
+
email: activeAccount.email,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Reset the credential cache. Internal use only (primarily for tests).
|
|
105
|
+
*/
|
|
106
|
+
export function resetCredentialCache() {
|
|
107
|
+
cachedCredential = null;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../../src/providers/antigravity/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/providers/antigravity/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/providers/antigravity/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type IQuotaProvider } from "../../interfaces";
|
|
2
|
+
export interface QuotaIndicator {
|
|
3
|
+
threshold: number;
|
|
4
|
+
symbol: string;
|
|
5
|
+
}
|
|
6
|
+
export interface AntigravityConfig {
|
|
7
|
+
indicators?: QuotaIndicator[];
|
|
8
|
+
debug?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface QuotaInfo {
|
|
11
|
+
remainingFraction: number;
|
|
12
|
+
resetTime?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ModelConfig {
|
|
15
|
+
modelName: string;
|
|
16
|
+
label?: string;
|
|
17
|
+
quotaInfo?: QuotaInfo;
|
|
18
|
+
}
|
|
19
|
+
export interface CloudAccountInfo {
|
|
20
|
+
email?: string;
|
|
21
|
+
projectId?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface CloudQuotaResult {
|
|
24
|
+
account: CloudAccountInfo;
|
|
25
|
+
models: ModelConfig[];
|
|
26
|
+
timestamp: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function fetchCloudQuota(accessToken: string, projectId?: string, debugEnabled?: boolean): Promise<CloudQuotaResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Creates the Antigravity provider that returns flat, raw quota data.
|
|
31
|
+
* Grouping and aggregation is handled by the service layer via AggregatedGroups.
|
|
32
|
+
*/
|
|
33
|
+
export declare function createAntigravityProvider(config?: AntigravityConfig): IQuotaProvider;
|
|
34
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../../src/providers/antigravity/provider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,kBAAkB,CAAC;AAiBvE,MAAM,WAAW,cAAc;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAC9B,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAoBD,MAAM,WAAW,SAAS;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACrB;AAsID,wBAAsB,eAAe,CACjC,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAClB,YAAY,GAAE,OAAe,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAmC3B;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACrC,MAAM,GAAE,iBAAsB,GAC/B,cAAc,CAwFhB"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { formatRelativeTime } from "../../utils/time";
|
|
2
|
+
import { getCloudCredentials } from "./auth";
|
|
3
|
+
import { logger } from "../../logger";
|
|
4
|
+
const CLOUDCODE_ENDPOINTS = [
|
|
5
|
+
"https://daily-cloudcode-pa.sandbox.googleapis.com",
|
|
6
|
+
"https://autopush-cloudcode-pa.sandbox.googleapis.com",
|
|
7
|
+
"https://cloudcode-pa.googleapis.com",
|
|
8
|
+
];
|
|
9
|
+
const CLOUDCODE_HEADERS = {
|
|
10
|
+
"Content-Type": "application/json",
|
|
11
|
+
"User-Agent": "antigravity/1.11.5 windows/amd64",
|
|
12
|
+
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
|
|
13
|
+
"Client-Metadata": '{"ideType":"IDE_UNSPECIFIED","platform":"PLATFORM_UNSPECIFIED","pluginType":"GEMINI"}',
|
|
14
|
+
};
|
|
15
|
+
const DEFAULT_INDICATORS = [
|
|
16
|
+
{ threshold: 0.2, symbol: "!" },
|
|
17
|
+
{ threshold: 0.05, symbol: "!!" },
|
|
18
|
+
];
|
|
19
|
+
function getIndicatorSymbol(fraction, indicators = DEFAULT_INDICATORS) {
|
|
20
|
+
if (indicators.length === 0)
|
|
21
|
+
return "";
|
|
22
|
+
const sorted = [...indicators].sort((a, b) => a.threshold - b.threshold);
|
|
23
|
+
for (const indicator of sorted) {
|
|
24
|
+
if (fraction <= indicator.threshold) {
|
|
25
|
+
return ` ${indicator.symbol}`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return "";
|
|
29
|
+
}
|
|
30
|
+
async function fetchAvailableModels(accessToken, projectId, debugEnabled) {
|
|
31
|
+
const payload = projectId ? { project: projectId } : {};
|
|
32
|
+
let lastError = null;
|
|
33
|
+
const headers = {
|
|
34
|
+
...CLOUDCODE_HEADERS,
|
|
35
|
+
Authorization: `Bearer ${accessToken}`,
|
|
36
|
+
};
|
|
37
|
+
for (const endpoint of CLOUDCODE_ENDPOINTS) {
|
|
38
|
+
try {
|
|
39
|
+
const url = `${endpoint}/v1internal:fetchAvailableModels`;
|
|
40
|
+
const controller = new AbortController();
|
|
41
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
42
|
+
try {
|
|
43
|
+
if (debugEnabled) {
|
|
44
|
+
logger.debug("antigravity:request", {
|
|
45
|
+
endpoint,
|
|
46
|
+
url,
|
|
47
|
+
hasProjectId: !!projectId,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const response = await fetch(url, {
|
|
51
|
+
method: "POST",
|
|
52
|
+
headers,
|
|
53
|
+
body: JSON.stringify(payload),
|
|
54
|
+
signal: controller.signal,
|
|
55
|
+
});
|
|
56
|
+
if (debugEnabled) {
|
|
57
|
+
logger.debug("antigravity:response_meta", {
|
|
58
|
+
endpoint,
|
|
59
|
+
status: response.status,
|
|
60
|
+
ok: response.ok,
|
|
61
|
+
contentType: response.headers.get("content-type"),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (response.status === 401) {
|
|
65
|
+
throw new Error("Authorization expired or invalid.");
|
|
66
|
+
}
|
|
67
|
+
if (response.status === 403) {
|
|
68
|
+
throw new Error("Access forbidden (403). Check your account permissions.");
|
|
69
|
+
}
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
const text = await response.text();
|
|
72
|
+
if (debugEnabled) {
|
|
73
|
+
logger.debug("antigravity:error_body", {
|
|
74
|
+
endpoint,
|
|
75
|
+
status: response.status,
|
|
76
|
+
bodyPreview: text.slice(0, 2000),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
throw new Error(`Cloud Code API error ${response.status}: ${text.slice(0, 200)}`);
|
|
80
|
+
}
|
|
81
|
+
const json = (await response.json());
|
|
82
|
+
const modelCount = Object.keys(json.models || {}).length;
|
|
83
|
+
if (debugEnabled) {
|
|
84
|
+
logger.debug("antigravity:fetch_success", { modelCount });
|
|
85
|
+
}
|
|
86
|
+
if (debugEnabled) {
|
|
87
|
+
const sampleKeys = Object.keys(json.models || {}).slice(0, 8);
|
|
88
|
+
const sanitizedSample = {};
|
|
89
|
+
for (const key of sampleKeys) {
|
|
90
|
+
sanitizedSample[key] = json.models?.[key];
|
|
91
|
+
}
|
|
92
|
+
logger.debug("antigravity:raw_response_sample", {
|
|
93
|
+
modelCount,
|
|
94
|
+
sampleKeys,
|
|
95
|
+
sample: sanitizedSample,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return json;
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
clearTimeout(timeoutId);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
lastError =
|
|
106
|
+
error instanceof Error ? error : new Error(String(error));
|
|
107
|
+
if (lastError.message.includes("Authorization") ||
|
|
108
|
+
lastError.message.includes("forbidden") ||
|
|
109
|
+
lastError.message.includes("invalid_grant")) {
|
|
110
|
+
throw lastError;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
throw lastError || new Error("All Cloud Code API endpoints failed");
|
|
115
|
+
}
|
|
116
|
+
export async function fetchCloudQuota(accessToken, projectId, debugEnabled = false) {
|
|
117
|
+
if (!accessToken) {
|
|
118
|
+
throw new Error("Access token is required for cloud quota fetching");
|
|
119
|
+
}
|
|
120
|
+
const response = await fetchAvailableModels(accessToken, projectId, debugEnabled);
|
|
121
|
+
const models = [];
|
|
122
|
+
if (response.models) {
|
|
123
|
+
for (const [modelKey, info] of Object.entries(response.models)) {
|
|
124
|
+
if (!info.quotaInfo)
|
|
125
|
+
continue;
|
|
126
|
+
models.push({
|
|
127
|
+
modelName: info.model || modelKey,
|
|
128
|
+
label: info.displayName || modelKey,
|
|
129
|
+
quotaInfo: {
|
|
130
|
+
remainingFraction: info.quotaInfo.remainingFraction ?? 0,
|
|
131
|
+
resetTime: info.quotaInfo.resetTime,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
account: {
|
|
138
|
+
projectId,
|
|
139
|
+
},
|
|
140
|
+
models,
|
|
141
|
+
timestamp: Date.now(),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Creates the Antigravity provider that returns flat, raw quota data.
|
|
146
|
+
* Grouping and aggregation is handled by the service layer via AggregatedGroups.
|
|
147
|
+
*/
|
|
148
|
+
export function createAntigravityProvider(config = {}) {
|
|
149
|
+
return {
|
|
150
|
+
id: "antigravity",
|
|
151
|
+
async fetchQuota() {
|
|
152
|
+
const debugEnabled = !!config.debug;
|
|
153
|
+
logger.debug("provider:antigravity:fetch_start", {
|
|
154
|
+
configDebug: config.debug,
|
|
155
|
+
});
|
|
156
|
+
// Fetch cloud credentials (Google OAuth)
|
|
157
|
+
let credentials;
|
|
158
|
+
try {
|
|
159
|
+
credentials = await getCloudCredentials();
|
|
160
|
+
if (debugEnabled) {
|
|
161
|
+
logger.debug("provider:antigravity:auth_ok", {
|
|
162
|
+
projectId: credentials.projectId,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch (e) {
|
|
167
|
+
logger.error("provider:antigravity:auth_failed", e);
|
|
168
|
+
throw e;
|
|
169
|
+
}
|
|
170
|
+
// Fetch live quota from Antigravity Cloud API
|
|
171
|
+
const cloudResult = await fetchCloudQuota(credentials.accessToken, credentials.projectId, debugEnabled);
|
|
172
|
+
if (debugEnabled) {
|
|
173
|
+
logger.debug("provider:antigravity:cloud_ok", {
|
|
174
|
+
modelCount: cloudResult.models.length,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
// Return flat list of all models with quota info
|
|
178
|
+
const entries = [];
|
|
179
|
+
for (const model of cloudResult.models) {
|
|
180
|
+
if (!model.quotaInfo ||
|
|
181
|
+
typeof model.quotaInfo.remainingFraction !== "number") {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const label = model.label || model.modelName || "";
|
|
185
|
+
const remainingFraction = model.quotaInfo.remainingFraction;
|
|
186
|
+
const usedPercent = Math.max(0, Math.min(100, (1 - remainingFraction) * 100));
|
|
187
|
+
// Generate stable raw ID from model name
|
|
188
|
+
const rawId = `ag-raw-${label
|
|
189
|
+
.toLowerCase()
|
|
190
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
191
|
+
.replace(/^-|-$/g, "")}`;
|
|
192
|
+
const indicator = getIndicatorSymbol(remainingFraction, config.indicators);
|
|
193
|
+
let reset;
|
|
194
|
+
if (model.quotaInfo.resetTime) {
|
|
195
|
+
reset = `resets in ${formatRelativeTime(new Date(model.quotaInfo.resetTime))}`;
|
|
196
|
+
}
|
|
197
|
+
entries.push({
|
|
198
|
+
id: rawId,
|
|
199
|
+
providerName: `Antigravity ${label}`,
|
|
200
|
+
used: usedPercent,
|
|
201
|
+
limit: 100,
|
|
202
|
+
unit: "%",
|
|
203
|
+
reset,
|
|
204
|
+
info: indicator.trim() || undefined,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
if (debugEnabled) {
|
|
208
|
+
logger.debug("provider:antigravity:fetch_ok", {
|
|
209
|
+
count: entries.length,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return entries;
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../../src/providers/antigravity/provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../../src/providers/codex.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAyPpE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,CAoC/D;AAED,wBAAgB,mBAAmB,IAAI,cAAc,CAqCpD"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { AUTH_FILE } from "../utils/paths";
|
|
3
|
+
import { logger } from "../logger";
|
|
4
|
+
const AUTH_PATH = AUTH_FILE();
|
|
5
|
+
const DEFAULT_BASE_URL = "https://chatgpt.com/backend-api";
|
|
6
|
+
const REQUEST_TIMEOUT_MS = 15_000;
|
|
7
|
+
const MAX_ERROR_BODY_CHARS = 2_000;
|
|
8
|
+
async function readAuthFile() {
|
|
9
|
+
try {
|
|
10
|
+
const raw = await readFile(AUTH_PATH, "utf8");
|
|
11
|
+
const parsed = JSON.parse(raw);
|
|
12
|
+
return parsed;
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
logger.debug("provider:codex:auth_read_failed", { authPath: AUTH_PATH, error: e });
|
|
16
|
+
// Fallback: try the config directory location
|
|
17
|
+
try {
|
|
18
|
+
const configPath = AUTH_PATH.replace("auth.json", "antigravity-accounts.json");
|
|
19
|
+
// If the replacement is not valid, this will likely fail and we return null
|
|
20
|
+
const rawConfig = await readFile(configPath, "utf8");
|
|
21
|
+
return JSON.parse(rawConfig);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function pickOauthAuth(auth) {
|
|
29
|
+
const preferred = ["opencode", "codex", "openai"];
|
|
30
|
+
for (const providerID of preferred) {
|
|
31
|
+
const info = auth[providerID];
|
|
32
|
+
if (info?.type === "oauth") {
|
|
33
|
+
return {
|
|
34
|
+
providerID,
|
|
35
|
+
access: info.access,
|
|
36
|
+
enterpriseUrl: info.enterpriseUrl,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
for (const [providerID, info] of Object.entries(auth)) {
|
|
41
|
+
if (info.type === "oauth") {
|
|
42
|
+
return {
|
|
43
|
+
providerID,
|
|
44
|
+
access: info.access,
|
|
45
|
+
enterpriseUrl: info.enterpriseUrl,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
function buildUsageUrl(baseUrl) {
|
|
52
|
+
const trimmed = baseUrl.replace(/\/+$/, "");
|
|
53
|
+
if (trimmed.includes("/backend-api")) {
|
|
54
|
+
return `${trimmed}/wham/usage`;
|
|
55
|
+
}
|
|
56
|
+
return `${trimmed}/api/codex/usage`;
|
|
57
|
+
}
|
|
58
|
+
async function fetchQuotaPayload(accessToken, baseUrl) {
|
|
59
|
+
const url = buildUsageUrl(baseUrl);
|
|
60
|
+
const controller = new AbortController();
|
|
61
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetch(url, {
|
|
64
|
+
headers: {
|
|
65
|
+
Authorization: `Bearer ${accessToken}`,
|
|
66
|
+
},
|
|
67
|
+
signal: controller.signal,
|
|
68
|
+
});
|
|
69
|
+
const bodyText = await response.text();
|
|
70
|
+
let payload = null;
|
|
71
|
+
try {
|
|
72
|
+
payload = JSON.parse(bodyText);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
payload = bodyText;
|
|
76
|
+
}
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
const error = new Error(`quota request failed (${response.status})`);
|
|
79
|
+
error.cause = {
|
|
80
|
+
status: response.status,
|
|
81
|
+
bodyText: bodyText.slice(0, MAX_ERROR_BODY_CHARS),
|
|
82
|
+
};
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
return payload;
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
clearTimeout(timeout);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function isObject(value) {
|
|
92
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
93
|
+
}
|
|
94
|
+
function toNumber(value) {
|
|
95
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
if (typeof value === "string") {
|
|
99
|
+
const parsed = Number.parseFloat(value);
|
|
100
|
+
if (Number.isFinite(parsed))
|
|
101
|
+
return parsed;
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
function describeWindow(windowSeconds) {
|
|
106
|
+
if (!windowSeconds || windowSeconds <= 0)
|
|
107
|
+
return null;
|
|
108
|
+
const minutes = Math.round(windowSeconds / 60);
|
|
109
|
+
if (minutes >= 60 && minutes % 60 === 0) {
|
|
110
|
+
const hours = minutes / 60;
|
|
111
|
+
return `${hours}h window`;
|
|
112
|
+
}
|
|
113
|
+
return `${minutes}m window`;
|
|
114
|
+
}
|
|
115
|
+
function formatRelativeSeconds(seconds) {
|
|
116
|
+
if (seconds <= 0)
|
|
117
|
+
return "now";
|
|
118
|
+
const minutes = Math.floor(seconds / 60);
|
|
119
|
+
const hours = Math.floor(minutes / 60);
|
|
120
|
+
const remainingMinutes = minutes % 60;
|
|
121
|
+
if (hours > 0) {
|
|
122
|
+
return `${hours}h ${remainingMinutes}m`;
|
|
123
|
+
}
|
|
124
|
+
return `${minutes}m`;
|
|
125
|
+
}
|
|
126
|
+
function parseRateLimitWindow(id, label, snapshot) {
|
|
127
|
+
const usedPercent = toNumber(snapshot.used_percent);
|
|
128
|
+
if (usedPercent === null)
|
|
129
|
+
return null;
|
|
130
|
+
// Window info
|
|
131
|
+
let window;
|
|
132
|
+
const windowSeconds = toNumber(snapshot.limit_window_seconds);
|
|
133
|
+
const windowLabel = describeWindow(windowSeconds);
|
|
134
|
+
if (windowLabel)
|
|
135
|
+
window = windowLabel;
|
|
136
|
+
// Reset info
|
|
137
|
+
let reset;
|
|
138
|
+
const resetAfter = toNumber(snapshot.reset_after_seconds);
|
|
139
|
+
const resetAt = toNumber(snapshot.reset_at);
|
|
140
|
+
if (resetAfter !== null) {
|
|
141
|
+
reset = `resets in ${formatRelativeSeconds(resetAfter)}`;
|
|
142
|
+
}
|
|
143
|
+
else if (resetAt !== null) {
|
|
144
|
+
reset = `resets at ${new Date(resetAt * 1000).toLocaleTimeString()}`;
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
id: `codex-${id}`,
|
|
148
|
+
providerName: `Codex ${label}`,
|
|
149
|
+
used: Math.max(0, Math.min(100, usedPercent)),
|
|
150
|
+
limit: 100,
|
|
151
|
+
unit: "%",
|
|
152
|
+
window,
|
|
153
|
+
reset,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function parseCredits(credits) {
|
|
157
|
+
const base = {
|
|
158
|
+
id: "codex-credits",
|
|
159
|
+
providerName: "Codex Credits",
|
|
160
|
+
unit: "credits",
|
|
161
|
+
};
|
|
162
|
+
if (credits.unlimited) {
|
|
163
|
+
return {
|
|
164
|
+
...base,
|
|
165
|
+
used: 0,
|
|
166
|
+
limit: null,
|
|
167
|
+
info: "unlimited",
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const balance = toNumber(credits.balance ?? null);
|
|
171
|
+
if (balance === null)
|
|
172
|
+
return null;
|
|
173
|
+
return {
|
|
174
|
+
...base,
|
|
175
|
+
used: balance,
|
|
176
|
+
limit: null,
|
|
177
|
+
info: "balance",
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
export function extractCodexQuota(payload) {
|
|
181
|
+
if (!isObject(payload))
|
|
182
|
+
return [];
|
|
183
|
+
const rateLimitCandidate = payload["rate_limit"];
|
|
184
|
+
const rateLimit = isObject(rateLimitCandidate) ? rateLimitCandidate : null;
|
|
185
|
+
const entries = [];
|
|
186
|
+
if (rateLimit) {
|
|
187
|
+
const primary = isObject(rateLimit.primary_window)
|
|
188
|
+
? rateLimit.primary_window
|
|
189
|
+
: null;
|
|
190
|
+
const secondary = isObject(rateLimit.secondary_window)
|
|
191
|
+
? rateLimit.secondary_window
|
|
192
|
+
: null;
|
|
193
|
+
if (primary) {
|
|
194
|
+
const entry = parseRateLimitWindow("primary", "Primary", primary);
|
|
195
|
+
if (entry)
|
|
196
|
+
entries.push(entry);
|
|
197
|
+
}
|
|
198
|
+
if (secondary) {
|
|
199
|
+
const entry = parseRateLimitWindow("secondary", "Secondary", secondary);
|
|
200
|
+
if (entry)
|
|
201
|
+
entries.push(entry);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
const creditsCandidate = payload["credits"];
|
|
205
|
+
const credits = isObject(creditsCandidate) ? creditsCandidate : null;
|
|
206
|
+
if (credits) {
|
|
207
|
+
const creditEntry = parseCredits(credits);
|
|
208
|
+
if (creditEntry)
|
|
209
|
+
entries.push(creditEntry);
|
|
210
|
+
}
|
|
211
|
+
return entries;
|
|
212
|
+
}
|
|
213
|
+
export function createCodexProvider() {
|
|
214
|
+
return {
|
|
215
|
+
id: "codex",
|
|
216
|
+
async fetchQuota() {
|
|
217
|
+
logger.debug("provider:codex:fetch_start", { authPath: AUTH_PATH });
|
|
218
|
+
const auth = await readAuthFile();
|
|
219
|
+
if (!auth) {
|
|
220
|
+
logger.debug("provider:codex:no_auth", { authPath: AUTH_PATH });
|
|
221
|
+
throw new Error("Codex auth.json not found");
|
|
222
|
+
}
|
|
223
|
+
const oauth = pickOauthAuth(auth);
|
|
224
|
+
if (!oauth) {
|
|
225
|
+
logger.debug("provider:codex:no_oauth", { availableProviders: Object.keys(auth) });
|
|
226
|
+
throw new Error("Codex OAuth credentials missing");
|
|
227
|
+
}
|
|
228
|
+
const baseUrl = process.env.OPENCODE_CODEX_BASE_URL ??
|
|
229
|
+
oauth.enterpriseUrl ??
|
|
230
|
+
DEFAULT_BASE_URL;
|
|
231
|
+
logger.debug("provider:codex:request", { providerID: oauth.providerID, baseUrl, url: buildUsageUrl(baseUrl) });
|
|
232
|
+
const payload = await fetchQuotaPayload(oauth.access, baseUrl);
|
|
233
|
+
const entries = extractCodexQuota(payload);
|
|
234
|
+
logger.debug("provider:codex:parse", { count: entries.length });
|
|
235
|
+
if (entries.length === 0) {
|
|
236
|
+
throw new Error("Codex quota payload did not include rate limits");
|
|
237
|
+
}
|
|
238
|
+
return entries;
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../src/providers/codex.ts"],"names":[],"mappings":"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"}
|