@slkiser/opencode-quota 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.
- package/LICENSE +21 -0
- package/README.md +103 -0
- package/dist/data/modelsdev-pricing.min.json +504 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cache.d.ts +49 -0
- package/dist/lib/cache.d.ts.map +1 -0
- package/dist/lib/cache.js +127 -0
- package/dist/lib/cache.js.map +1 -0
- package/dist/lib/config.d.ts +30 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +154 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/copilot.d.ts +25 -0
- package/dist/lib/copilot.d.ts.map +1 -0
- package/dist/lib/copilot.js +306 -0
- package/dist/lib/copilot.js.map +1 -0
- package/dist/lib/entries.d.ts +60 -0
- package/dist/lib/entries.d.ts.map +1 -0
- package/dist/lib/entries.js +8 -0
- package/dist/lib/entries.js.map +1 -0
- package/dist/lib/firmware.d.ts +15 -0
- package/dist/lib/firmware.d.ts.map +1 -0
- package/dist/lib/firmware.js +79 -0
- package/dist/lib/firmware.js.map +1 -0
- package/dist/lib/format.d.ts +16 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +99 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/google-token-cache.d.ts +30 -0
- package/dist/lib/google-token-cache.d.ts.map +1 -0
- package/dist/lib/google-token-cache.js +100 -0
- package/dist/lib/google-token-cache.js.map +1 -0
- package/dist/lib/google.d.ts +43 -0
- package/dist/lib/google.d.ts.map +1 -0
- package/dist/lib/google.js +399 -0
- package/dist/lib/google.js.map +1 -0
- package/dist/lib/markdown-table.d.ts +8 -0
- package/dist/lib/markdown-table.d.ts.map +1 -0
- package/dist/lib/markdown-table.js +56 -0
- package/dist/lib/markdown-table.js.map +1 -0
- package/dist/lib/modelsdev-pricing.d.ts +23 -0
- package/dist/lib/modelsdev-pricing.d.ts.map +1 -0
- package/dist/lib/modelsdev-pricing.js +32 -0
- package/dist/lib/modelsdev-pricing.js.map +1 -0
- package/dist/lib/openai.d.ts +33 -0
- package/dist/lib/openai.d.ts.map +1 -0
- package/dist/lib/openai.js +162 -0
- package/dist/lib/openai.js.map +1 -0
- package/dist/lib/opencode-auth.d.ts +11 -0
- package/dist/lib/opencode-auth.d.ts.map +1 -0
- package/dist/lib/opencode-auth.js +27 -0
- package/dist/lib/opencode-auth.js.map +1 -0
- package/dist/lib/opencode-storage.d.ts +45 -0
- package/dist/lib/opencode-storage.d.ts.map +1 -0
- package/dist/lib/opencode-storage.js +120 -0
- package/dist/lib/opencode-storage.js.map +1 -0
- package/dist/lib/quota-command-format.d.ts +14 -0
- package/dist/lib/quota-command-format.d.ts.map +1 -0
- package/dist/lib/quota-command-format.js +122 -0
- package/dist/lib/quota-command-format.js.map +1 -0
- package/dist/lib/quota-stats-format.d.ts +9 -0
- package/dist/lib/quota-stats-format.d.ts.map +1 -0
- package/dist/lib/quota-stats-format.js +244 -0
- package/dist/lib/quota-stats-format.js.map +1 -0
- package/dist/lib/quota-stats.d.ts +71 -0
- package/dist/lib/quota-stats.d.ts.map +1 -0
- package/dist/lib/quota-stats.js +270 -0
- package/dist/lib/quota-stats.js.map +1 -0
- package/dist/lib/quota-status.d.ts +23 -0
- package/dist/lib/quota-status.d.ts.map +1 -0
- package/dist/lib/quota-status.js +112 -0
- package/dist/lib/quota-status.js.map +1 -0
- package/dist/lib/toast-format-grouped.d.ts +25 -0
- package/dist/lib/toast-format-grouped.d.ts.map +1 -0
- package/dist/lib/toast-format-grouped.js +123 -0
- package/dist/lib/toast-format-grouped.js.map +1 -0
- package/dist/lib/types.d.ts +218 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +39 -0
- package/dist/lib/types.js.map +1 -0
- package/dist/plugin.d.ts +13 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +633 -0
- package/dist/plugin.js.map +1 -0
- package/dist/providers/copilot.d.ts +8 -0
- package/dist/providers/copilot.d.ts.map +1 -0
- package/dist/providers/copilot.js +50 -0
- package/dist/providers/copilot.js.map +1 -0
- package/dist/providers/firmware.d.ts +6 -0
- package/dist/providers/firmware.d.ts.map +1 -0
- package/dist/providers/firmware.js +52 -0
- package/dist/providers/firmware.js.map +1 -0
- package/dist/providers/google-antigravity.d.ts +6 -0
- package/dist/providers/google-antigravity.d.ts.map +1 -0
- package/dist/providers/google-antigravity.js +77 -0
- package/dist/providers/google-antigravity.js.map +1 -0
- package/dist/providers/openai.d.ts +6 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +106 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/registry.d.ts +8 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +14 -0
- package/dist/providers/registry.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-token-cache.d.ts","sourceRoot":"","sources":["../../src/lib/google-token-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,MAAM,WAAW,2BAA2B;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAqBD,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,MAAM,CAUT;AA4CD,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,CAO9C;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,2BAA2B,CAAC;CACpC,GAAG,OAAO,CAAC,IAAI,CAAC,CAKhB;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAG3D"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent access-token cache for Google Antigravity accounts.
|
|
3
|
+
*
|
|
4
|
+
* Why:
|
|
5
|
+
* - Antigravity quota is multi-account; each account needs its own access token.
|
|
6
|
+
* - Refreshing on every toast is noisy and increases timeout risk.
|
|
7
|
+
* - We persist access tokens so restarts don't force immediate refresh.
|
|
8
|
+
*/
|
|
9
|
+
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
10
|
+
import { homedir } from "os";
|
|
11
|
+
import { dirname, join } from "path";
|
|
12
|
+
import { createHash } from "crypto";
|
|
13
|
+
const CACHE_VERSION = 1;
|
|
14
|
+
let memCache = null;
|
|
15
|
+
let loadPromise = null;
|
|
16
|
+
function getCacheBaseDir() {
|
|
17
|
+
const home = homedir();
|
|
18
|
+
if (process.platform === "win32") {
|
|
19
|
+
return process.env.LOCALAPPDATA || join(home, "AppData", "Local");
|
|
20
|
+
}
|
|
21
|
+
return process.env.XDG_CACHE_HOME || join(home, ".cache");
|
|
22
|
+
}
|
|
23
|
+
export function getGoogleTokenCachePath() {
|
|
24
|
+
return join(getCacheBaseDir(), "opencode-quota", "google-access-tokens.json");
|
|
25
|
+
}
|
|
26
|
+
export function makeAccountCacheKey(params) {
|
|
27
|
+
const emailPart = (params.email ?? "").trim().toLowerCase();
|
|
28
|
+
const hash = createHash("sha256")
|
|
29
|
+
.update(params.refreshToken)
|
|
30
|
+
.update("\n")
|
|
31
|
+
.update(params.projectId)
|
|
32
|
+
.digest("hex")
|
|
33
|
+
.slice(0, 16);
|
|
34
|
+
// Keep a human hint without making it sensitive.
|
|
35
|
+
return `${emailPart}::${params.projectId}::${hash}`;
|
|
36
|
+
}
|
|
37
|
+
async function loadFromDisk(path) {
|
|
38
|
+
try {
|
|
39
|
+
const raw = await readFile(path, "utf-8");
|
|
40
|
+
const parsed = JSON.parse(raw);
|
|
41
|
+
if (!parsed || typeof parsed !== "object")
|
|
42
|
+
throw new Error("invalid");
|
|
43
|
+
const file = parsed;
|
|
44
|
+
if (file.version !== CACHE_VERSION || typeof file.tokens !== "object" || !file.tokens) {
|
|
45
|
+
throw new Error("invalid");
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
version: CACHE_VERSION,
|
|
49
|
+
updatedAt: typeof file.updatedAt === "number" ? file.updatedAt : Date.now(),
|
|
50
|
+
tokens: file.tokens,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return { version: CACHE_VERSION, updatedAt: Date.now(), tokens: {} };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async function ensureLoaded() {
|
|
58
|
+
if (memCache)
|
|
59
|
+
return memCache;
|
|
60
|
+
if (loadPromise)
|
|
61
|
+
return loadPromise;
|
|
62
|
+
const path = getGoogleTokenCachePath();
|
|
63
|
+
loadPromise = (async () => {
|
|
64
|
+
const file = await loadFromDisk(path);
|
|
65
|
+
memCache = file;
|
|
66
|
+
loadPromise = null;
|
|
67
|
+
return file;
|
|
68
|
+
})();
|
|
69
|
+
return loadPromise;
|
|
70
|
+
}
|
|
71
|
+
async function persist() {
|
|
72
|
+
if (!memCache)
|
|
73
|
+
return;
|
|
74
|
+
const path = getGoogleTokenCachePath();
|
|
75
|
+
const dir = dirname(path);
|
|
76
|
+
await mkdir(dir, { recursive: true });
|
|
77
|
+
await writeFile(path, JSON.stringify(memCache, null, 2), "utf-8");
|
|
78
|
+
}
|
|
79
|
+
export async function getCachedAccessToken(params) {
|
|
80
|
+
const cache = await ensureLoaded();
|
|
81
|
+
const entry = cache.tokens[params.key];
|
|
82
|
+
if (!entry)
|
|
83
|
+
return null;
|
|
84
|
+
if (typeof entry.expiresAt !== "number")
|
|
85
|
+
return null;
|
|
86
|
+
if (entry.expiresAt <= Date.now() + params.skewMs)
|
|
87
|
+
return null;
|
|
88
|
+
return entry;
|
|
89
|
+
}
|
|
90
|
+
export async function setCachedAccessToken(params) {
|
|
91
|
+
const cache = await ensureLoaded();
|
|
92
|
+
cache.tokens[params.key] = params.entry;
|
|
93
|
+
cache.updatedAt = Date.now();
|
|
94
|
+
await persist();
|
|
95
|
+
}
|
|
96
|
+
export async function clearGoogleTokenCache() {
|
|
97
|
+
memCache = { version: CACHE_VERSION, updatedAt: Date.now(), tokens: {} };
|
|
98
|
+
await persist();
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=google-token-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-token-cache.js","sourceRoot":"","sources":["../../src/lib/google-token-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Antigravity quota fetcher
|
|
3
|
+
*
|
|
4
|
+
* Uses OpenCode's antigravity-accounts.json at ~/.config/opencode/antigravity-accounts.json.
|
|
5
|
+
* Requires the user to have opencode-antigravity-auth installed and logged in.
|
|
6
|
+
*/
|
|
7
|
+
import type { AntigravityAccount, GoogleModelId, GoogleResult } from "./types.js";
|
|
8
|
+
export declare function getAntigravityAccountsCandidatePaths(): string[];
|
|
9
|
+
export declare function pickAntigravityAccountsPath(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Read Antigravity accounts from storage
|
|
12
|
+
*/
|
|
13
|
+
export declare function readAntigravityAccounts(): Promise<AntigravityAccount[] | null>;
|
|
14
|
+
export declare function hasAntigravityAccountsConfigured(): Promise<boolean>;
|
|
15
|
+
export declare function refreshGoogleTokensForAllAccounts(params?: {
|
|
16
|
+
skewMs?: number;
|
|
17
|
+
force?: boolean;
|
|
18
|
+
}): Promise<null | {
|
|
19
|
+
total: number;
|
|
20
|
+
successCount: number;
|
|
21
|
+
failures: Array<{
|
|
22
|
+
email?: string;
|
|
23
|
+
error: string;
|
|
24
|
+
}>;
|
|
25
|
+
}>;
|
|
26
|
+
/**
|
|
27
|
+
* Query Google Antigravity quota for ALL accounts
|
|
28
|
+
*
|
|
29
|
+
* Reads accounts from ~/.config/opencode/antigravity-accounts.json.
|
|
30
|
+
* Refreshes access tokens and fetches quota for all accounts in parallel.
|
|
31
|
+
*
|
|
32
|
+
* @param modelIds - Model IDs to fetch quota for
|
|
33
|
+
* @returns Quota result with all models and any errors, or null if not configured
|
|
34
|
+
*/
|
|
35
|
+
export declare function queryGoogleQuota(modelIds: GoogleModelId[]): Promise<GoogleResult>;
|
|
36
|
+
/**
|
|
37
|
+
* Format Google quota for toast display
|
|
38
|
+
*
|
|
39
|
+
* @param result - Google quota result
|
|
40
|
+
* @returns Formatted string like "G3Pro 100% * G3Flash 100% * Claude 0%" or null
|
|
41
|
+
*/
|
|
42
|
+
export declare function formatGoogleQuota(result: GoogleResult): string | null;
|
|
43
|
+
//# sourceMappingURL=google.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../src/lib/google.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,OAAO,KAAK,EACV,kBAAkB,EAKlB,aAAa,EAEb,YAAY,EACb,MAAM,YAAY,CAAC;AA4BpB,wBAAgB,oCAAoC,IAAI,MAAM,EAAE,CAwB/D;AAED,wBAAgB,2BAA2B,IAAI,MAAM,CAMpD;AAED;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,kBAAkB,EAAE,GAAG,IAAI,CAAC,CAmBpF;AAED,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,OAAO,CAAC,CAGzE;AAsHD,wBAAsB,iCAAiC,CAAC,MAAM,CAAC,EAAE;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CACP,IAAI,GACJ;IACE,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,KAAK,CAAC;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD,CACJ,CAmCA;AA+KD;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAsCvF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CAcrE"}
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Antigravity quota fetcher
|
|
3
|
+
*
|
|
4
|
+
* Uses OpenCode's antigravity-accounts.json at ~/.config/opencode/antigravity-accounts.json.
|
|
5
|
+
* Requires the user to have opencode-antigravity-auth installed and logged in.
|
|
6
|
+
*/
|
|
7
|
+
import { readFile } from "fs/promises";
|
|
8
|
+
import { homedir } from "os";
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
import { existsSync } from "fs";
|
|
11
|
+
import { ANTIGRAVITY_CLIENT_ID as GOOGLE_CLIENT_ID, ANTIGRAVITY_CLIENT_SECRET as GOOGLE_CLIENT_SECRET, } from "opencode-antigravity-auth/dist/src/constants.js";
|
|
12
|
+
import { REQUEST_TIMEOUT_MS, GOOGLE_MODEL_KEYS } from "./types.js";
|
|
13
|
+
import { getCachedAccessToken, makeAccountCacheKey, setCachedAccessToken, } from "./google-token-cache.js";
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// Constants
|
|
16
|
+
// =============================================================================
|
|
17
|
+
const GOOGLE_QUOTA_API_URL = "https://cloudcode-pa.googleapis.com/v1internal:fetchAvailableModels";
|
|
18
|
+
const USER_AGENT = "antigravity/1.11.9 darwin/arm64";
|
|
19
|
+
const GOOGLE_TOKEN_REFRESH_URL = "https://oauth2.googleapis.com/token";
|
|
20
|
+
// Network timeouts tuned for reliability.
|
|
21
|
+
const GOOGLE_TOKEN_TIMEOUT_MS = 8000;
|
|
22
|
+
const GOOGLE_QUOTA_TIMEOUT_MS = 6000;
|
|
23
|
+
// Multi-account fetching concurrency (reliability > speed).
|
|
24
|
+
const GOOGLE_ACCOUNTS_CONCURRENCY = 3;
|
|
25
|
+
// =============================================================================
|
|
26
|
+
// Helpers
|
|
27
|
+
// =============================================================================
|
|
28
|
+
export function getAntigravityAccountsCandidatePaths() {
|
|
29
|
+
const home = homedir();
|
|
30
|
+
const isWindows = process.platform === "win32";
|
|
31
|
+
// Match common storage resolution used by opencode-antigravity-auth variants.
|
|
32
|
+
// - Config: $XDG_CONFIG_HOME/opencode (or ~/.config/opencode)
|
|
33
|
+
// - Data: $XDG_DATA_HOME/opencode (or ~/.local/share/opencode)
|
|
34
|
+
// - Windows: %APPDATA%/opencode (configBase), dataBase==configBase
|
|
35
|
+
const configBaseDir = isWindows
|
|
36
|
+
? process.env.APPDATA || join(home, "AppData", "Roaming")
|
|
37
|
+
: process.env.XDG_CONFIG_HOME || join(home, ".config");
|
|
38
|
+
const xdgDataBase = isWindows
|
|
39
|
+
? configBaseDir
|
|
40
|
+
: process.env.XDG_DATA_HOME || join(home, ".local", "share");
|
|
41
|
+
const candidates = [
|
|
42
|
+
join(configBaseDir, "opencode", "antigravity-accounts.json"),
|
|
43
|
+
join(xdgDataBase, "opencode", "antigravity-accounts.json"),
|
|
44
|
+
];
|
|
45
|
+
// Unique + stable order.
|
|
46
|
+
return Array.from(new Set(candidates));
|
|
47
|
+
}
|
|
48
|
+
export function pickAntigravityAccountsPath() {
|
|
49
|
+
for (const p of getAntigravityAccountsCandidatePaths()) {
|
|
50
|
+
if (existsSync(p))
|
|
51
|
+
return p;
|
|
52
|
+
}
|
|
53
|
+
// Default to the first candidate for error/debug messaging.
|
|
54
|
+
return getAntigravityAccountsCandidatePaths()[0];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Read Antigravity accounts from storage
|
|
58
|
+
*/
|
|
59
|
+
export async function readAntigravityAccounts() {
|
|
60
|
+
for (const path of getAntigravityAccountsCandidatePaths()) {
|
|
61
|
+
try {
|
|
62
|
+
const content = await readFile(path, "utf-8");
|
|
63
|
+
const file = JSON.parse(content);
|
|
64
|
+
if (!file.accounts || file.accounts.length === 0) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
// Filter to accounts with refresh tokens
|
|
68
|
+
const validAccounts = file.accounts.filter((account) => account.refreshToken);
|
|
69
|
+
return validAccounts.length > 0 ? validAccounts : null;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// try next candidate
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
export async function hasAntigravityAccountsConfigured() {
|
|
78
|
+
const accounts = await readAntigravityAccounts();
|
|
79
|
+
return !!accounts && accounts.length > 0;
|
|
80
|
+
}
|
|
81
|
+
async function mapWithConcurrency(params) {
|
|
82
|
+
const n = Math.max(1, Math.trunc(params.concurrency));
|
|
83
|
+
const results = new Array(params.items.length);
|
|
84
|
+
let nextIndex = 0;
|
|
85
|
+
const workers = Array.from({ length: Math.min(n, params.items.length) }, async () => {
|
|
86
|
+
while (true) {
|
|
87
|
+
const idx = nextIndex++;
|
|
88
|
+
if (idx >= params.items.length)
|
|
89
|
+
return;
|
|
90
|
+
results[idx] = await params.fn(params.items[idx], idx);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
await Promise.all(workers);
|
|
94
|
+
return results;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Refresh Google access token
|
|
98
|
+
*/
|
|
99
|
+
async function refreshAccessToken(refreshToken, timeoutMs = GOOGLE_TOKEN_TIMEOUT_MS) {
|
|
100
|
+
try {
|
|
101
|
+
const params = new URLSearchParams({
|
|
102
|
+
client_id: GOOGLE_CLIENT_ID,
|
|
103
|
+
client_secret: GOOGLE_CLIENT_SECRET,
|
|
104
|
+
refresh_token: refreshToken,
|
|
105
|
+
grant_type: "refresh_token",
|
|
106
|
+
});
|
|
107
|
+
const response = await fetchWithTimeout(GOOGLE_TOKEN_REFRESH_URL, {
|
|
108
|
+
method: "POST",
|
|
109
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
110
|
+
body: params,
|
|
111
|
+
}, timeoutMs);
|
|
112
|
+
if (!response.ok) {
|
|
113
|
+
// Try to extract error code from response
|
|
114
|
+
try {
|
|
115
|
+
const errorData = (await response.json());
|
|
116
|
+
if (errorData.error === "invalid_grant") {
|
|
117
|
+
return { error: "Token revoked" };
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
error: errorData.error_description || `HTTP ${response.status}`,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return { error: `HTTP ${response.status}` };
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const data = (await response.json());
|
|
128
|
+
return {
|
|
129
|
+
accessToken: data.access_token,
|
|
130
|
+
expiresIn: data.expires_in,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
if (err instanceof Error && err.message.includes("timeout")) {
|
|
135
|
+
return { error: "Token refresh timeout" };
|
|
136
|
+
}
|
|
137
|
+
return { error: "Token refresh failed" };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async function refreshAccessTokenWithCache(params) {
|
|
141
|
+
const skewMs = params.skewMs ?? 2 * 60_000;
|
|
142
|
+
const key = makeAccountCacheKey({
|
|
143
|
+
refreshToken: params.refreshToken,
|
|
144
|
+
projectId: params.projectId,
|
|
145
|
+
email: params.email,
|
|
146
|
+
});
|
|
147
|
+
if (!params.force) {
|
|
148
|
+
const cached = await getCachedAccessToken({ key, skewMs });
|
|
149
|
+
if (cached)
|
|
150
|
+
return { accessToken: cached.accessToken };
|
|
151
|
+
}
|
|
152
|
+
const refreshed = await refreshAccessToken(params.refreshToken);
|
|
153
|
+
if ("error" in refreshed)
|
|
154
|
+
return refreshed;
|
|
155
|
+
await setCachedAccessToken({
|
|
156
|
+
key,
|
|
157
|
+
entry: {
|
|
158
|
+
accessToken: refreshed.accessToken,
|
|
159
|
+
expiresAt: Date.now() + Math.max(1, refreshed.expiresIn) * 1000,
|
|
160
|
+
projectId: params.projectId,
|
|
161
|
+
email: params.email,
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
return { accessToken: refreshed.accessToken };
|
|
165
|
+
}
|
|
166
|
+
export async function refreshGoogleTokensForAllAccounts(params) {
|
|
167
|
+
const accounts = await readAntigravityAccounts();
|
|
168
|
+
if (!accounts || accounts.length === 0)
|
|
169
|
+
return null;
|
|
170
|
+
const valid = accounts.filter((a) => !!a.refreshToken);
|
|
171
|
+
if (valid.length === 0)
|
|
172
|
+
return null;
|
|
173
|
+
const results = await mapWithConcurrency({
|
|
174
|
+
items: valid,
|
|
175
|
+
concurrency: GOOGLE_ACCOUNTS_CONCURRENCY,
|
|
176
|
+
fn: async (account) => {
|
|
177
|
+
const email = account.email;
|
|
178
|
+
const projectId = getProjectId(account);
|
|
179
|
+
if (!projectId)
|
|
180
|
+
return { ok: false, email, error: "No projectId" };
|
|
181
|
+
const token = await refreshAccessTokenWithCache({
|
|
182
|
+
refreshToken: account.refreshToken,
|
|
183
|
+
projectId,
|
|
184
|
+
email,
|
|
185
|
+
skewMs: params?.skewMs,
|
|
186
|
+
force: params?.force,
|
|
187
|
+
});
|
|
188
|
+
if ("error" in token)
|
|
189
|
+
return { ok: false, email, error: token.error };
|
|
190
|
+
return { ok: true, email };
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
const failures = results.filter((r) => !r.ok).map((r) => ({ email: r.email, error: r.error }));
|
|
194
|
+
const successCount = results.filter((r) => r.ok).length;
|
|
195
|
+
return {
|
|
196
|
+
total: valid.length,
|
|
197
|
+
successCount,
|
|
198
|
+
failures,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Fetch with timeout
|
|
203
|
+
*/
|
|
204
|
+
async function fetchWithTimeout(url, options, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
205
|
+
const controller = new AbortController();
|
|
206
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
207
|
+
try {
|
|
208
|
+
const response = await fetch(url, {
|
|
209
|
+
...options,
|
|
210
|
+
signal: controller.signal,
|
|
211
|
+
});
|
|
212
|
+
return response;
|
|
213
|
+
}
|
|
214
|
+
catch (err) {
|
|
215
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
216
|
+
throw new Error(`Request timeout after ${Math.round(timeoutMs / 1000)}s`);
|
|
217
|
+
}
|
|
218
|
+
throw err;
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
clearTimeout(timeoutId);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Fetch quota from Google API
|
|
226
|
+
*/
|
|
227
|
+
async function fetchGoogleQuota(accessToken, projectId, timeoutMs = GOOGLE_QUOTA_TIMEOUT_MS) {
|
|
228
|
+
const response = await fetchWithTimeout(GOOGLE_QUOTA_API_URL, {
|
|
229
|
+
method: "POST",
|
|
230
|
+
headers: {
|
|
231
|
+
"Content-Type": "application/json",
|
|
232
|
+
Authorization: `Bearer ${accessToken}`,
|
|
233
|
+
"User-Agent": USER_AGENT,
|
|
234
|
+
},
|
|
235
|
+
body: JSON.stringify({ project: projectId }),
|
|
236
|
+
}, timeoutMs);
|
|
237
|
+
if (!response.ok) {
|
|
238
|
+
if (response.status === 401 || response.status === 403) {
|
|
239
|
+
throw new Error(`Google API auth error: ${response.status}`);
|
|
240
|
+
}
|
|
241
|
+
throw new Error(`Google API error: ${response.status}`);
|
|
242
|
+
}
|
|
243
|
+
return response.json();
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Extract model quotas from API response
|
|
247
|
+
*/
|
|
248
|
+
function extractModelQuotas(data, modelIds, accountEmail) {
|
|
249
|
+
const quotas = [];
|
|
250
|
+
for (const modelId of modelIds) {
|
|
251
|
+
const modelConfig = GOOGLE_MODEL_KEYS[modelId];
|
|
252
|
+
if (!modelConfig)
|
|
253
|
+
continue;
|
|
254
|
+
let modelInfo = data.models[modelConfig.key];
|
|
255
|
+
// Try alternate key if primary not found
|
|
256
|
+
if (!modelInfo && modelConfig.altKey) {
|
|
257
|
+
modelInfo = data.models[modelConfig.altKey];
|
|
258
|
+
}
|
|
259
|
+
if (modelInfo) {
|
|
260
|
+
const remainingFraction = modelInfo.quotaInfo?.remainingFraction ?? 0;
|
|
261
|
+
quotas.push({
|
|
262
|
+
modelId,
|
|
263
|
+
displayName: modelConfig.display,
|
|
264
|
+
percentRemaining: Math.round(remainingFraction * 100),
|
|
265
|
+
resetTimeIso: modelInfo.quotaInfo?.resetTime,
|
|
266
|
+
accountEmail,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return quotas;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Fetch quota for a single account
|
|
274
|
+
*/
|
|
275
|
+
function getProjectId(account) {
|
|
276
|
+
return account.projectId || account.projectID || account.managedProjectId;
|
|
277
|
+
}
|
|
278
|
+
// NOTE: This plugin treats Google Antigravity as truly multi-account.
|
|
279
|
+
// Each account gets its own access token derived from its refresh token.
|
|
280
|
+
async function fetchAccountQuotaWithAntigravityRefresh(params) {
|
|
281
|
+
const email = params.account.email || "Unknown";
|
|
282
|
+
const projectId = getProjectId(params.account);
|
|
283
|
+
if (!projectId) {
|
|
284
|
+
return { success: false, error: "No projectId", accountEmail: email };
|
|
285
|
+
}
|
|
286
|
+
try {
|
|
287
|
+
const tokenResult = await refreshAccessTokenWithCache({
|
|
288
|
+
refreshToken: params.account.refreshToken,
|
|
289
|
+
projectId,
|
|
290
|
+
email,
|
|
291
|
+
});
|
|
292
|
+
if ("error" in tokenResult)
|
|
293
|
+
return { success: false, error: tokenResult.error, accountEmail: email };
|
|
294
|
+
let data;
|
|
295
|
+
try {
|
|
296
|
+
data = await fetchGoogleQuota(tokenResult.accessToken, projectId);
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
// One auth retry: refresh token then retry quota call.
|
|
300
|
+
if (err instanceof Error && err.message.includes("auth error")) {
|
|
301
|
+
const retryToken = await refreshAccessToken(params.account.refreshToken);
|
|
302
|
+
if ("error" in retryToken) {
|
|
303
|
+
return { success: false, error: retryToken.error, accountEmail: email };
|
|
304
|
+
}
|
|
305
|
+
await setCachedAccessToken({
|
|
306
|
+
key: makeAccountCacheKey({ refreshToken: params.account.refreshToken, projectId, email }),
|
|
307
|
+
entry: {
|
|
308
|
+
accessToken: retryToken.accessToken,
|
|
309
|
+
expiresAt: Date.now() + Math.max(1, retryToken.expiresIn) * 1000,
|
|
310
|
+
projectId,
|
|
311
|
+
email,
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
data = await fetchGoogleQuota(retryToken.accessToken, projectId);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
throw err;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
const models = extractModelQuotas(data, params.modelIds, email);
|
|
321
|
+
return { success: true, models, accountEmail: email };
|
|
322
|
+
}
|
|
323
|
+
catch (err) {
|
|
324
|
+
if (err instanceof Error && err.message.includes("timeout")) {
|
|
325
|
+
return { success: false, error: "API timeout", accountEmail: email };
|
|
326
|
+
}
|
|
327
|
+
return {
|
|
328
|
+
success: false,
|
|
329
|
+
error: err instanceof Error ? err.message : String(err),
|
|
330
|
+
accountEmail: email,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
// =============================================================================
|
|
335
|
+
// Export
|
|
336
|
+
// =============================================================================
|
|
337
|
+
/**
|
|
338
|
+
* Query Google Antigravity quota for ALL accounts
|
|
339
|
+
*
|
|
340
|
+
* Reads accounts from ~/.config/opencode/antigravity-accounts.json.
|
|
341
|
+
* Refreshes access tokens and fetches quota for all accounts in parallel.
|
|
342
|
+
*
|
|
343
|
+
* @param modelIds - Model IDs to fetch quota for
|
|
344
|
+
* @returns Quota result with all models and any errors, or null if not configured
|
|
345
|
+
*/
|
|
346
|
+
export async function queryGoogleQuota(modelIds) {
|
|
347
|
+
const accounts = await readAntigravityAccounts();
|
|
348
|
+
if (!accounts || accounts.length === 0) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
// Query accounts with bounded concurrency (reliability > speed).
|
|
352
|
+
const results = await mapWithConcurrency({
|
|
353
|
+
items: accounts,
|
|
354
|
+
concurrency: GOOGLE_ACCOUNTS_CONCURRENCY,
|
|
355
|
+
fn: async (account) => fetchAccountQuotaWithAntigravityRefresh({ account, modelIds }),
|
|
356
|
+
});
|
|
357
|
+
// Collect all successful models and errors
|
|
358
|
+
const allModels = [];
|
|
359
|
+
const errors = [];
|
|
360
|
+
for (const result of results) {
|
|
361
|
+
if (result.success && result.models && result.models.length > 0) {
|
|
362
|
+
allModels.push(...result.models);
|
|
363
|
+
}
|
|
364
|
+
else if (!result.success && result.error && result.accountEmail) {
|
|
365
|
+
errors.push({ email: result.accountEmail, error: result.error });
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
// Return combined result
|
|
369
|
+
if (allModels.length === 0 && errors.length === 0) {
|
|
370
|
+
return {
|
|
371
|
+
success: false,
|
|
372
|
+
error: "No quota data available",
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
return {
|
|
376
|
+
success: true,
|
|
377
|
+
models: allModels,
|
|
378
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Format Google quota for toast display
|
|
383
|
+
*
|
|
384
|
+
* @param result - Google quota result
|
|
385
|
+
* @returns Formatted string like "G3Pro 100% * G3Flash 100% * Claude 0%" or null
|
|
386
|
+
*/
|
|
387
|
+
export function formatGoogleQuota(result) {
|
|
388
|
+
if (!result) {
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
if (!result.success) {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
if (result.models.length === 0) {
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
397
|
+
return result.models.map((m) => `${m.displayName} ${m.percentRemaining}%`).join(" \u2022 ");
|
|
398
|
+
}
|
|
399
|
+
//# sourceMappingURL=google.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.js","sourceRoot":"","sources":["../../src/lib/google.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAEhC,OAAO,EACL,qBAAqB,IAAI,gBAAgB,EACzC,yBAAyB,IAAI,oBAAoB,GAClD,MAAM,iDAAiD,CAAC;AAYzD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AAEjC,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF,MAAM,oBAAoB,GAAG,qEAAqE,CAAC;AACnG,MAAM,UAAU,GAAG,iCAAiC,CAAC;AAErD,MAAM,wBAAwB,GAAG,qCAAqC,CAAC;AAEvE,0CAA0C;AAC1C,MAAM,uBAAuB,GAAG,IAAI,CAAC;AACrC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAErC,4DAA4D;AAC5D,MAAM,2BAA2B,GAAG,CAAC,CAAC;AAEtC,gFAAgF;AAChF,UAAU;AACV,gFAAgF;AAEhF,MAAM,UAAU,oCAAoC;IAClD,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC;IAE/C,8EAA8E;IAC9E,8DAA8D;IAC9D,+DAA+D;IAC/D,mEAAmE;IAEnE,MAAM,aAAa,GAAG,SAAS;QAC7B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC;QACzD,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAEzD,MAAM,WAAW,GAAG,SAAS;QAC3B,CAAC,CAAC,aAAa;QACf,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAE/D,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,aAAa,EAAE,UAAU,EAAE,2BAA2B,CAAC;QAC5D,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,2BAA2B,CAAC;KAC3D,CAAC;IAEF,yBAAyB;IACzB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,2BAA2B;IACzC,KAAK,MAAM,CAAC,IAAI,oCAAoC,EAAE,EAAE,CAAC;QACvD,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IACD,4DAA4D;IAC5D,OAAO,oCAAoC,EAAE,CAAC,CAAC,CAAE,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,KAAK,MAAM,IAAI,IAAI,oCAAoC,EAAE,EAAE,CAAC;QAC1D,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;YAE5D,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjD,SAAS;YACX,CAAC;YAED,yCAAyC;YACzC,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC9E,OAAO,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,qBAAqB;QACvB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gCAAgC;IACpD,MAAM,QAAQ,GAAG,MAAM,uBAAuB,EAAE,CAAC;IACjD,OAAO,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAO,MAIvC;IACC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,IAAI,KAAK,CAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAClD,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,IAAI,EAAE;QAClF,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;YACxB,IAAI,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM;gBAAE,OAAO;YACvC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAE,EAAE,GAAG,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,kBAAkB,CAC/B,YAAoB,EACpB,YAAoB,uBAAuB;IAE3C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YACjC,SAAS,EAAE,gBAAgB;YAC3B,aAAa,EAAE,oBAAoB;YACnC,aAAa,EAAE,YAAY;YAC3B,UAAU,EAAE,eAAe;SAC5B,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CACrC,wBAAwB,EACxB;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,mCAAmC,EAAE;YAChE,IAAI,EAAE,MAAM;SACb,EACD,SAAS,CACV,CAAC;QAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,0CAA0C;YAC1C,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAGvC,CAAC;gBACF,IAAI,SAAS,CAAC,KAAK,KAAK,eAAe,EAAE,CAAC;oBACxC,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;gBACpC,CAAC;gBACD,OAAO;oBACL,KAAK,EAAE,SAAS,CAAC,iBAAiB,IAAI,QAAQ,QAAQ,CAAC,MAAM,EAAE;iBAChE,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,KAAK,EAAE,QAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9C,CAAC;QACH,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAGlC,CAAC;QAEF,OAAO;YACL,WAAW,EAAE,IAAI,CAAC,YAAY;YAC9B,SAAS,EAAE,IAAI,CAAC,UAAU;SAC3B,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5D,OAAO,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;QAC5C,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,KAAK,UAAU,2BAA2B,CAAC,MAM1C;IACC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC;IAC3C,MAAM,GAAG,GAAG,mBAAmB,CAAC;QAC9B,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,IAAI,MAAM;YAAE,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC;IACzD,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAChE,IAAI,OAAO,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAE3C,MAAM,oBAAoB,CAAC;QACzB,GAAG;QACH,KAAK,EAAE;YACL,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,IAAI;YAC/D,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB;KACF,CAAC,CAAC;IAEH,OAAO,EAAE,WAAW,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,MAGvD;IAQC,MAAM,QAAQ,GAAG,MAAM,uBAAuB,EAAE,CAAC;IACjD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpD,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACvD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpC,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC;QACvC,KAAK,EAAE,KAAK;QACZ,WAAW,EAAE,2BAA2B;QACxC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACpB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;YAC5B,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;YACxC,IAAI,CAAC,SAAS;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAc,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;YAE5E,MAAM,KAAK,GAAG,MAAM,2BAA2B,CAAC;gBAC9C,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,SAAS;gBACT,KAAK;gBACL,MAAM,EAAE,MAAM,EAAE,MAAM;gBACtB,KAAK,EAAE,MAAM,EAAE,KAAK;aACrB,CAAC,CAAC;YACH,IAAI,OAAO,IAAI,KAAK;gBAAE,OAAO,EAAE,EAAE,EAAE,KAAc,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;YAC/E,OAAO,EAAE,EAAE,EAAE,IAAa,EAAE,KAAK,EAAE,CAAC;QACtC,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC/F,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;IAExD,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,YAAY;QACZ,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,gBAAgB,CAC7B,GAAW,EACX,OAAoB,EACpB,YAAoB,kBAAkB;IAEtC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IAElE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,GAAG,OAAO;YACV,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACtD,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5E,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,SAAS,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,gBAAgB,CAC7B,WAAmB,EACnB,SAAiB,EACjB,YAAoB,uBAAuB;IAE3C,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CACrC,oBAAoB,EACpB;QACE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,WAAW,EAAE;YACtC,YAAY,EAAE,UAAU;SACzB;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;KAC7C,EACD,SAAS,CACV,CAAC;IAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAkC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CACzB,IAAyB,EACzB,QAAyB,EACzB,YAAqB;IAErB,MAAM,MAAM,GAAuB,EAAE,CAAC;IAEtC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC/C,IAAI,CAAC,WAAW;YAAE,SAAS;QAE3B,IAAI,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAE7C,yCAAyC;QACzC,IAAI,CAAC,SAAS,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;YACrC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,iBAAiB,GAAG,SAAS,CAAC,SAAS,EAAE,iBAAiB,IAAI,CAAC,CAAC;YACtE,MAAM,CAAC,IAAI,CAAC;gBACV,OAAO;gBACP,WAAW,EAAE,WAAW,CAAC,OAAO;gBAChC,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,iBAAiB,GAAG,GAAG,CAAC;gBACrD,YAAY,EAAE,SAAS,CAAC,SAAS,EAAE,SAAS;gBAC5C,YAAY;aACb,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,OAA2B;IAC/C,OAAO,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,gBAAgB,CAAC;AAC5E,CAAC;AAED,sEAAsE;AACtE,yEAAyE;AAEzE,KAAK,UAAU,uCAAuC,CAAC,MAGtD;IAMC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,SAAS,CAAC;IAChD,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAE/C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACxE,CAAC;IAED,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,2BAA2B,CAAC;YACpD,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY;YACzC,SAAS;YACT,KAAK;SACN,CAAC,CAAC;QAEH,IAAI,OAAO,IAAI,WAAW;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;QAErG,IAAI,IAAyB,CAAC;QAC9B,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,uDAAuD;YACvD,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC/D,MAAM,UAAU,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;gBACzE,IAAI,OAAO,IAAI,UAAU,EAAE,CAAC;oBAC1B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;gBAC1E,CAAC;gBACD,MAAM,oBAAoB,CAAC;oBACzB,GAAG,EAAE,mBAAmB,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;oBACzF,KAAK,EAAE;wBACL,WAAW,EAAE,UAAU,CAAC,WAAW;wBACnC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI;wBAChE,SAAS;wBACT,KAAK;qBACN;iBACF,CAAC,CAAC;gBACH,IAAI,GAAG,MAAM,gBAAgB,CAAC,UAAU,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;YACnE,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,CAAC;YACZ,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAEhE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACxD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;QACvE,CAAC;QACD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YACvD,YAAY,EAAE,KAAK;SACpB,CAAC;IACJ,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,SAAS;AACT,gFAAgF;AAEhF;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAyB;IAC9D,MAAM,QAAQ,GAAG,MAAM,uBAAuB,EAAE,CAAC;IACjD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iEAAiE;IACjE,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC;QACvC,KAAK,EAAE,QAAQ;QACf,WAAW,EAAE,2BAA2B;QACxC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,uCAAuC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;KACtF,CAAC,CAAC;IAEH,2CAA2C;IAC3C,MAAM,SAAS,GAAuB,EAAE,CAAC;IACzC,MAAM,MAAM,GAAyB,EAAE,CAAC;IAExC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChE,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC;aAAM,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YAClE,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,YAAY,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,yBAAyB;SACjC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;KAC1B,CAAC;AACzB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAoB;IACpD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,gBAAgB,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC9F,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-table.d.ts","sourceRoot":"","sources":["../../src/lib/markdown-table.ts"],"names":[],"mappings":"AAAA,KAAK,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAqBzC,wBAAgB,mBAAmB,CAAC,MAAM,EAAE;IAC1C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;IACjB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;CAClB,GAAG,MAAM,CAsCT"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
function padCell(text, width, align) {
|
|
2
|
+
const s = text ?? "";
|
|
3
|
+
const len = s.length;
|
|
4
|
+
if (len >= width)
|
|
5
|
+
return s;
|
|
6
|
+
const pad = width - len;
|
|
7
|
+
if (align === "right")
|
|
8
|
+
return " ".repeat(pad) + s;
|
|
9
|
+
if (align === "center") {
|
|
10
|
+
const left = Math.floor(pad / 2);
|
|
11
|
+
const right = pad - left;
|
|
12
|
+
return " ".repeat(left) + s + " ".repeat(right);
|
|
13
|
+
}
|
|
14
|
+
return s + " ".repeat(pad);
|
|
15
|
+
}
|
|
16
|
+
function escapeCell(text) {
|
|
17
|
+
// Keep this conservative: tool output should be plain ascii.
|
|
18
|
+
return (text ?? "").replace(/\|/g, "\\|").replace(/\r?\n/g, " ");
|
|
19
|
+
}
|
|
20
|
+
export function renderMarkdownTable(params) {
|
|
21
|
+
const aligns = params.aligns ?? params.headers.map(() => "left");
|
|
22
|
+
const colCount = params.headers.length;
|
|
23
|
+
const safeRows = params.rows.map((r) => {
|
|
24
|
+
const out = [];
|
|
25
|
+
for (let i = 0; i < colCount; i++)
|
|
26
|
+
out.push(escapeCell(r[i] ?? ""));
|
|
27
|
+
return out;
|
|
28
|
+
});
|
|
29
|
+
const headerCells = params.headers.map((h) => escapeCell(h));
|
|
30
|
+
const widths = headerCells.map((h) => Math.max(3, h.length));
|
|
31
|
+
for (const row of safeRows) {
|
|
32
|
+
for (let i = 0; i < colCount; i++) {
|
|
33
|
+
widths[i] = Math.max(widths[i], (row[i] ?? "").length);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const fmtRow = (cells) => `| ${cells
|
|
37
|
+
.map((c, i) => padCell(c, widths[i], aligns[i] ?? "left"))
|
|
38
|
+
.join(" | ")} |`;
|
|
39
|
+
const sep = `| ${widths
|
|
40
|
+
.map((w, i) => {
|
|
41
|
+
const a = aligns[i] ?? "left";
|
|
42
|
+
if (a === "right")
|
|
43
|
+
return "-".repeat(Math.max(3, w - 1)) + ":";
|
|
44
|
+
if (a === "center")
|
|
45
|
+
return ":" + "-".repeat(Math.max(3, w - 2)) + ":";
|
|
46
|
+
return "-".repeat(Math.max(3, w));
|
|
47
|
+
})
|
|
48
|
+
.join(" | ")} |`;
|
|
49
|
+
const lines = [];
|
|
50
|
+
lines.push(fmtRow(headerCells));
|
|
51
|
+
lines.push(sep);
|
|
52
|
+
for (const row of safeRows)
|
|
53
|
+
lines.push(fmtRow(row));
|
|
54
|
+
return lines.join("\n");
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=markdown-table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-table.js","sourceRoot":"","sources":["../../src/lib/markdown-table.ts"],"names":[],"mappings":"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"}
|