feat(usage): add xAI quota reporting #2628

feat(usage): add xAI quota reporting
This commit is contained in:
Bohdan Triapitsyn
2026-08-07 11:48:56 +03:00
committed by GitHub
9 changed files with 832 additions and 7 deletions
@@ -76,6 +76,9 @@ export const UsagePage: React.FC = () => {
const providerMeta = QUOTA_PROVIDERS.find((provider) => provider.id === selectedProviderId);
const providerName = providerMeta?.name ?? selectedProviderId ?? t('settings.usage.sidebar.title');
const usage = selectedResult?.usage;
const selectedProviderError = selectedResult?.configured && !selectedResult.ok
? selectedResult.error
: null;
const showInDropdown = selectedProviderId ? dropdownProviderIds.includes(selectedProviderId) : false;
const hasCredentialsForm = selectedProviderId === 'opencode-go' || selectedProviderId === 'ollama-cloud' || selectedProviderId === 'cursor';
const handleDropdownToggle = React.useCallback((enabled: boolean) => {
@@ -179,10 +182,10 @@ export const UsagePage: React.FC = () => {
<p className="typography-ui-label text-foreground pb-8">{t('settings.usage.page.state.noData')}</p>
)}
{error && (
{(error || selectedProviderError) && (
<div className="mb-8 rounded-lg border border-[var(--status-error-border)] bg-[var(--status-error-background)] px-4 py-3">
<p className="typography-ui-label font-medium text-[var(--status-error)]">{t('settings.usage.page.state.refreshFailedTitle')}</p>
<p className="typography-meta text-[var(--status-error)]/80 mt-1">{error}</p>
<p className="typography-meta text-[var(--status-error)]/80 mt-1">{error ?? selectedProviderError}</p>
</div>
)}
@@ -24,4 +24,5 @@ export const QUOTA_PROVIDERS: QuotaProviderMeta[] = [
{ id: 'crof', name: 'CrofAI' },
{ id: 'deepseek', name: 'DeepSeek' },
{ id: 'neuralwatt', name: 'NeuralWatt' },
{ id: 'xai', name: 'xAI' },
];
+2 -1
View File
@@ -18,7 +18,8 @@ export type QuotaProviderId =
| 'opencode-go'
| 'crof'
| 'deepseek'
| 'neuralwatt';
| 'neuralwatt'
| 'xai';
export interface UsageWindow {
usedPercent: number | null;
+11 -1
View File
@@ -5,7 +5,7 @@ import os from 'node:os';
const OPENCODE_DATA_DIR = path.join(os.homedir(), '.local', 'share', 'opencode');
const AUTH_FILE = path.join(OPENCODE_DATA_DIR, 'auth.json');
type AuthEntry = Record<string, unknown>;
export type AuthEntry = Record<string, unknown>;
type AuthFile = Record<string, AuthEntry>;
const readAuthFile = (): AuthFile => {
@@ -46,6 +46,16 @@ const writeAuthFile = (auth: AuthFile): void => {
}
};
export const updateProviderAuth = (providerId: string, entry: AuthEntry): void => {
if (!providerId || typeof providerId !== 'string') {
throw new Error('Provider ID is required');
}
const auth = readAuthFile();
auth[providerId] = entry;
writeAuthFile(auth);
};
export const removeProviderAuth = (providerId: string): boolean => {
if (!providerId || typeof providerId !== 'string') {
throw new Error('Provider ID is required');
+404 -1
View File
@@ -3,6 +3,7 @@ import path from 'node:path';
import os from 'node:os';
import { fetchOpenCodeGoUsage } from './opencodeGoQuota';
import { readCredential } from './quotaCredentials';
import { getProviderAuth, updateProviderAuth } from './opencodeAuth';
type AuthEntry = Record<string, unknown> | string;
type AuthFile = Record<string, AuthEntry>;
@@ -174,6 +175,21 @@ const OPENCODE_CONFIG_DIR = path.join(os.homedir(), '.config', 'opencode');
const OPENCODE_DATA_DIR = path.join(os.homedir(), '.local', 'share', 'opencode');
const AUTH_FILE = path.join(OPENCODE_DATA_DIR, 'auth.json');
const XAI_USAGE_ENDPOINT = 'https://grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig';
const XAI_TOKEN_ENDPOINT = 'https://auth.x.ai/oauth2/token';
const XAI_CLIENT_ID = 'b1a00492-073a-47ea-816f-4c329264a828';
const XAI_REFRESH_SKEW_MS = 120_000;
const XAI_DEFAULT_EXPIRES_IN_SECONDS = 3600;
type XaiAuthEntry = Record<string, unknown> & {
type: 'oauth';
access?: string;
refresh?: string;
expires?: unknown;
};
let xaiRefreshPromise: Promise<XaiAuthEntry> | null = null;
const ANTIGRAVITY_ACCOUNTS_PATHS = [
path.join(OPENCODE_CONFIG_DIR, 'antigravity-accounts.json'),
@@ -403,6 +419,304 @@ const buildResult = (data: {
fetchedAt: Date.now(),
});
const resolveXaiAuth = (): XaiAuthEntry | null => {
const entry = getProviderAuth('xai');
if (!entry || typeof entry !== 'object' || entry.type !== 'oauth') return null;
const access = asNonEmptyString(entry.access);
const refresh = asNonEmptyString(entry.refresh);
if (!access && !refresh) return null;
return {
...entry,
type: 'oauth',
...(access ? { access } : {}),
...(refresh ? { refresh } : {}),
...(entry.expires !== undefined ? { expires: entry.expires } : {}),
};
};
const jwtExpiryMilliseconds = (accessToken: string): number | null => {
const payload = accessToken.split('.')[1];
if (!payload) return null;
try {
const decoded = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8')) as Record<string, unknown>;
return typeof decoded.exp === 'number' && Number.isFinite(decoded.exp)
? decoded.exp * 1000
: null;
} catch {
return null;
}
};
const xaiAccessNeedsRefresh = (entry: XaiAuthEntry, now = Date.now()): boolean => {
const access = asNonEmptyString(entry.access);
if (!access) return true;
const refreshDeadline = now + XAI_REFRESH_SKEW_MS;
const storedExpiry = Number(entry.expires);
if (Number.isFinite(storedExpiry) && storedExpiry <= refreshDeadline) {
return true;
}
const jwtExpiry = jwtExpiryMilliseconds(access);
return jwtExpiry !== null && jwtExpiry <= refreshDeadline;
};
const refreshXaiAuth = (entry: XaiAuthEntry): Promise<XaiAuthEntry> => {
if (xaiRefreshPromise) return xaiRefreshPromise;
const refreshToken = asNonEmptyString(entry.refresh);
if (!refreshToken) {
return Promise.reject(new Error('xAI OAuth refresh token is unavailable'));
}
const pending = (async () => {
const response = await fetch(XAI_TOKEN_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
client_id: XAI_CLIENT_ID,
refresh_token: refreshToken,
grant_type: 'refresh_token',
}),
signal: AbortSignal.timeout(15_000),
});
const payload = await response.json().catch(() => null) as Record<string, unknown> | null;
if (!response.ok) {
throw new Error(`xAI OAuth refresh failed: ${response.status}`);
}
const responsePayload = payload ?? {};
const access = asNonEmptyString(responsePayload.access_token);
if (!access) {
throw new Error('xAI OAuth refresh returned no access token');
}
const expiresIn = responsePayload.expires_in ?? XAI_DEFAULT_EXPIRES_IN_SECONDS;
if (typeof expiresIn !== 'number' || !Number.isFinite(expiresIn)) {
throw new Error('xAI OAuth refresh returned an invalid expiry');
}
const refreshed: XaiAuthEntry = {
...entry,
type: 'oauth',
access,
refresh: asNonEmptyString(responsePayload.refresh_token) ?? refreshToken,
expires: Date.now() + expiresIn * 1000,
};
// Validate the new access token before updating the existing secure auth file.
updateProviderAuth('xai', refreshed);
return refreshed;
})();
const settled = pending.finally(() => {
if (xaiRefreshPromise === settled) {
xaiRefreshPromise = null;
}
});
xaiRefreshPromise = settled;
return settled;
};
const getXaiAccessToken = async (entry: XaiAuthEntry): Promise<string> => {
if (!xaiAccessNeedsRefresh(entry)) return entry.access!;
return (await refreshXaiAuth(entry)).access!;
};
type XaiFixed32Field = { path: number[]; value: number; order: number };
type XaiVarintField = { path: number[]; value: bigint };
type XaiProtobufScan = {
fixed32Fields: XaiFixed32Field[];
varintFields: XaiVarintField[];
nextOrder: number;
};
const readXaiVarint = (bytes: Uint8Array, index: { value: number }): bigint | null => {
let result = 0n;
for (let shift = 0n; index.value < bytes.length && shift < 64n; shift += 7n) {
const byte = bytes[index.value++];
if (shift === 63n && (byte & 0x7e) !== 0) return null;
result |= BigInt(byte & 0x7f) << shift;
if ((byte & 0x80) === 0) return result;
}
return null;
};
const scanXaiProtobuf = (
bytes: Uint8Array,
depth: number,
pathPrefix: number[],
scan: XaiProtobufScan,
): boolean => {
const index = { value: 0 };
while (index.value < bytes.length) {
const fieldKey = readXaiVarint(bytes, index);
if (fieldKey === null || fieldKey === 0n) return false;
const fieldNumber = Number(fieldKey >> 3n);
const wireType = Number(fieldKey & 0x07n);
if (fieldNumber < 1 || fieldNumber > 0x1fffffff) return false;
const fieldPath = [...pathPrefix, fieldNumber];
if (wireType === 0) {
const value = readXaiVarint(bytes, index);
if (value === null) return false;
scan.varintFields.push({ path: fieldPath, value });
continue;
}
if (wireType === 1) {
if (index.value + 8 > bytes.length) return false;
index.value += 8;
continue;
}
if (wireType === 2) {
const length = readXaiVarint(bytes, index);
if (length === null || length > BigInt(bytes.length - index.value)) return false;
const start = index.value;
index.value += Number(length);
if (depth >= 4 && length !== 0n) return false;
if (depth < 4) {
const nestedScan: XaiProtobufScan = {
fixed32Fields: [],
varintFields: [],
nextOrder: scan.nextOrder,
};
if (!scanXaiProtobuf(bytes.subarray(start, index.value), depth + 1, fieldPath, nestedScan)) return false;
scan.fixed32Fields.push(...nestedScan.fixed32Fields);
scan.varintFields.push(...nestedScan.varintFields);
scan.nextOrder = nestedScan.nextOrder;
}
continue;
}
if (wireType === 5) {
if (index.value + 4 > bytes.length) return false;
const value = new DataView(bytes.buffer, bytes.byteOffset + index.value, 4).getFloat32(0, true);
scan.fixed32Fields.push({ path: fieldPath, value, order: scan.nextOrder++ });
index.value += 4;
continue;
}
return false;
}
return true;
};
const looksLikeXaiProtobuf = (bytes: Uint8Array): boolean => {
if (!bytes.length) return false;
const fieldNumber = Math.floor(bytes[0] / 8);
const wireType = bytes[0] % 8;
return fieldNumber > 0 && [0, 1, 2, 5].includes(wireType);
};
const parseXaiGrpcTrailerStatus = (bytes: Uint8Array): number | null => {
let text: string;
try {
text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
} catch {
return null;
}
let status: number | null = null;
for (const line of text.split(/\r?\n/)) {
if (!line) continue;
const separator = line.indexOf(':');
if (separator <= 0) return null;
const key = line.slice(0, separator).trim().toLowerCase();
if (!key) return null;
if (key !== 'grpc-status') continue;
if (status !== null) return null;
const rawStatus = line.slice(separator + 1).trim();
if (!/^\d+$/.test(rawStatus)) return null;
status = Number(rawStatus);
if (!Number.isSafeInteger(status)) return null;
}
return status;
};
const parseXaiGrpcFrames = (bytes: Uint8Array): { payloads: Uint8Array[]; trailerStatuses: number[] } | null | false => {
if (bytes.length < 5 || (bytes[0] & 0x7f) !== 0) return null;
const payloads: Uint8Array[] = [];
const trailerStatuses: number[] = [];
let index = 0;
let sawTrailer = false;
while (index < bytes.length) {
if (index + 5 > bytes.length) return false;
const flags = bytes[index++];
if ((flags & 0x7f) !== 0) return false;
const length = (bytes[index++] * 0x1000000) + (bytes[index++] << 16) + (bytes[index++] << 8) + bytes[index++];
if (length > bytes.length - index) return false;
const frame = bytes.subarray(index, index + length);
index += length;
if (flags & 0x80) {
sawTrailer = true;
const status = parseXaiGrpcTrailerStatus(frame);
if (status === null) return false;
trailerStatuses.push(status);
} else {
if (sawTrailer) return false;
payloads.push(frame);
}
}
return { payloads, trailerStatuses };
};
const sameXaiPath = (left: number[], right: number[]) => (
left.length === right.length && left.every((value, index) => value === right[index])
);
const XAI_USAGE_PERCENT_PATHS = [[1], [1, 1]];
const isXaiUsagePercentPath = (path: number[]) => (
XAI_USAGE_PERCENT_PATHS.some((candidate) => sameXaiPath(candidate, path))
);
const parseXaiUsage = (bytes: Uint8Array): { usedPercent: number; resetAt: number | null } => {
const frames = parseXaiGrpcFrames(bytes);
if (frames === false) throw new Error('xAI returned malformed gRPC-web framing');
const payloads = frames === null
? (looksLikeXaiProtobuf(bytes) ? [bytes] : [])
: frames.payloads;
if (frames) {
for (const status of frames.trailerStatuses) {
if (status !== 0) throw new Error(`xAI billing RPC failed with status ${status}`);
}
}
if (!payloads.length) throw new Error('xAI returned an empty protobuf response');
const scan: XaiProtobufScan = { fixed32Fields: [], varintFields: [], nextOrder: 0 };
for (const payload of payloads) {
if (!scanXaiProtobuf(payload, 0, [], scan)) throw new Error('xAI returned malformed protobuf data');
}
const percentField = scan.fixed32Fields
.filter((field) => isXaiUsagePercentPath(field.path) && Number.isFinite(field.value) && field.value >= 0 && field.value <= 100)
.sort((left, right) => left.path.length - right.path.length || left.order - right.order)[0];
const resetCandidates = scan.varintFields
.filter((field) => field.value >= 1_700_000_000n && field.value <= 2_100_000_000n)
.map((field) => ({ path: field.path, seconds: Number(field.value) }))
.map((field) => ({ path: field.path, timestamp: field.seconds * 1000 }))
.filter((field) => field.timestamp > Date.now());
const preferredReset = resetCandidates
.filter((field) => sameXaiPath(field.path, [1, 5, 1]))
.sort((a, b) => a.timestamp - b.timestamp)[0];
const resetAt = (preferredReset ?? resetCandidates.sort((a, b) => a.timestamp - b.timestamp)[0])?.timestamp ?? null;
const hasUsagePeriod = scan.varintFields.some((field) => (
(field.path.length >= 2 && field.path[0] === 1 && field.path[1] === 6)
|| (sameXaiPath(field.path, [1, 8, 1]) && (field.value === 1n || field.value === 2n))
));
const noUsageYet = !percentField && scan.fixed32Fields.length === 0 && resetAt !== null && hasUsagePeriod;
const usedPercent = percentField?.value ?? (noUsageYet ? 0 : null);
if (usedPercent === null) throw new Error('xAI billing response did not contain usable current-period data');
return { usedPercent, resetAt };
};
const formatMoney = (value: number | null) => {
if (value === null || !Number.isFinite(value)) return null;
return value.toFixed(2);
@@ -425,7 +739,12 @@ const durationToSeconds = (duration?: number, unit?: string) => {
};
export const listConfiguredQuotaProviders = () => {
const auth = readAuthFile();
let auth: AuthFile = {};
try {
auth = readAuthFile();
} catch {
// Managed credentials remain enumerable; unreadable auth cannot establish xAI configuration.
}
const configured = new Set<string>();
if (readCredential('opencode-go')) configured.add('opencode-go');
if (readCredential('ollama-cloud')) configured.add('ollama-cloud');
@@ -507,6 +826,16 @@ export const listConfiguredQuotaProviders = () => {
configured.add('deepseek');
}
let xaiAuth: XaiAuthEntry | null = null;
try {
xaiAuth = resolveXaiAuth();
} catch {
xaiAuth = null;
}
if (xaiAuth) {
configured.add('xai');
}
return Array.from(configured);
};
@@ -2303,6 +2632,78 @@ const fetchDeepseekQuota = async (): Promise<ProviderResult> => {
}
};
const fetchXaiQuota = async (): Promise<ProviderResult> => {
try {
const entry = resolveXaiAuth();
if (!entry) {
return buildResult({
providerId: 'xai',
providerName: 'xAI',
ok: false,
configured: false,
error: 'Not configured',
});
}
const accessToken = await getXaiAccessToken(entry);
const response = await fetch(XAI_USAGE_ENDPOINT, {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
Origin: 'https://grok.com',
Referer: 'https://grok.com/?_s=usage',
Accept: '*/*',
'Content-Type': 'application/grpc-web+proto',
'x-grpc-web': '1',
'x-user-agent': 'connect-es/2.1.1',
'User-Agent': 'OpenChamber',
},
body: new Uint8Array([0, 0, 0, 0, 0]),
signal: AbortSignal.timeout(15_000),
});
const grpcStatus = response.headers.get('grpc-status');
if (grpcStatus !== null) {
const rawStatus = grpcStatus.trim();
if (!/^\d+$/.test(rawStatus)) throw new Error('xAI billing returned malformed gRPC status');
const status = Number(rawStatus);
if (!Number.isSafeInteger(status)) throw new Error('xAI billing returned malformed gRPC status');
if (status !== 0) {
throw new Error(`xAI billing RPC failed with status ${status}`);
}
}
if (!response.ok) {
throw new Error(`xAI billing API error: ${response.status}`);
}
const parsed = parseXaiUsage(new Uint8Array(await response.arrayBuffer()));
return buildResult({
providerId: 'xai',
providerName: 'xAI',
ok: true,
configured: true,
usage: {
windows: {
billing_cycle: toUsageWindow({
usedPercent: parsed.usedPercent,
windowSeconds: null,
resetAt: parsed.resetAt,
}),
},
},
});
} catch (error) {
return buildResult({
providerId: 'xai',
providerName: 'xAI',
ok: false,
configured: true,
error: error instanceof Error ? error.message : 'Request failed',
});
}
};
export const fetchQuotaForProvider = async (providerId: string): Promise<ProviderResult> => {
switch (providerId) {
case 'claude':
@@ -2350,6 +2751,8 @@ export const fetchQuotaForProvider = async (providerId: string): Promise<Provide
return fetchDeepseekQuota();
case 'neuralwatt':
return fetchNeuralwattQuota();
case 'xai':
return fetchXaiQuota();
default:
return buildResult({
providerId,
+5 -2
View File
@@ -25,16 +25,19 @@ function readAuthFile() {
function writeAuthFile(auth) {
try {
if (!fs.existsSync(OPENCODE_DATA_DIR)) {
fs.mkdirSync(OPENCODE_DATA_DIR, { recursive: true });
fs.mkdirSync(OPENCODE_DATA_DIR, { recursive: true, mode: 0o700 });
}
if (process.platform !== 'win32') fs.chmodSync(OPENCODE_DATA_DIR, 0o700);
if (fs.existsSync(AUTH_FILE)) {
const backupFile = `${AUTH_FILE}.openchamber.backup`;
fs.copyFileSync(AUTH_FILE, backupFile);
if (process.platform !== 'win32') fs.chmodSync(backupFile, 0o600);
console.log(`Created auth backup: ${backupFile}`);
}
fs.writeFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), 'utf8');
fs.writeFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), { encoding: 'utf8', mode: 0o600 });
if (process.platform !== 'win32') fs.chmodSync(AUTH_FILE, 0o600);
console.log('Successfully wrote auth file');
} catch (error) {
console.error('Failed to write auth file:', error);
@@ -35,6 +35,7 @@ These provider IDs are currently dispatchable via `fetchQuotaForProvider(provide
| `wafer` | Wafer.ai | `providers/wafer.js` | `wafer`, `wafer-ai`, `wafer_ai`, `wafer.ai` |
| `opencode-go` | OpenCode Go | `providers/opencode-go.js` | Manual workspace ID and auth cookie stored under `~/.config/openchamber/quota/` |
| `neuralwatt` | NeuralWatt | `providers/neuralwatt.js` | `neuralwatt` (API key under `key` or `token`) |
| `xai` | xAI | `providers/xai.js` | `xai` OAuth entry in OpenCode `auth.json` |
## Internal-only provider module
- `providers/openai.js` exists for logic parity/reuse but is intentionally not registered for dispatcher ID routing.
@@ -26,6 +26,7 @@ import * as neuralwatt from './neuralwatt.js';
import * as ollamaCloud from './ollama-cloud.js';
import * as wafer from './wafer.js';
import * as opencodeGo from './opencode-go.js';
import * as xai from './xai.js';
const registry = {
claude: {
@@ -141,6 +142,12 @@ const registry = {
providerName: neuralwatt.providerName,
isConfigured: neuralwatt.isConfigured,
fetchQuota: neuralwatt.fetchQuota
},
xai: {
providerId: xai.providerId,
providerName: xai.providerName,
isConfigured: xai.isConfigured,
fetchQuota: xai.fetchQuota
}
};
@@ -0,0 +1,396 @@
import { readAuthFile, writeAuthFile } from '../../opencode/auth.js';
import { buildResult, toUsageWindow } from '../utils/index.js';
export const providerId = 'xai';
export const providerName = 'xAI';
const USAGE_URL = 'https://grok.com/grok_api_v2.GrokBuildBilling/GetGrokCreditsConfig';
const TOKEN_URL = 'https://auth.x.ai/oauth2/token';
const CLIENT_ID = 'b1a00492-073a-47ea-816f-4c329264a828';
const REFRESH_SKEW_MS = 120_000;
const REQUEST_TIMEOUT_MS = 15_000;
const EMPTY_GRPC_WEB_BODY = new Uint8Array([0, 0, 0, 0, 0]);
let refreshPromise = null;
const nonEmptyString = (value) => {
if (typeof value !== 'string') return null;
const trimmed = value.trim();
return trimmed ? trimmed : null;
};
const readXaiAuth = () => {
try {
const entry = readAuthFile()?.xai;
if (!entry || typeof entry !== 'object' || entry.type !== 'oauth') {
return { entry: null, error: null };
}
if (!nonEmptyString(entry.access) && !nonEmptyString(entry.refresh)) {
return { entry: null, error: null };
}
return { entry, error: null };
} catch {
return { entry: null, error: 'Failed to read xAI OAuth credentials' };
}
};
const decodeJwtClaims = (token) => {
try {
const payload = token.split('.')[1];
if (!payload) return null;
return JSON.parse(Buffer.from(payload, 'base64url').toString('utf8'));
} catch {
return null;
}
};
const tokenNeedsRefresh = (entry) => {
const access = nonEmptyString(entry.access);
if (!access) return true;
const refreshDeadline = Date.now() + REFRESH_SKEW_MS;
const storedExpiry = Number(entry.expires);
if (Number.isFinite(storedExpiry) && storedExpiry <= refreshDeadline) return true;
const jwtExpiry = Number(decodeJwtClaims(access)?.exp) * 1000;
return Number.isFinite(jwtExpiry) && jwtExpiry <= refreshDeadline;
};
const refreshXaiOauth = async (entry) => {
if (!refreshPromise) {
refreshPromise = (async () => {
const refreshToken = nonEmptyString(entry.refresh);
if (!refreshToken) {
throw new Error('xAI OAuth entry has no usable refresh token');
}
const response = await fetch(TOKEN_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
client_id: CLIENT_ID,
refresh_token: refreshToken,
grant_type: 'refresh_token'
}),
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
});
if (!response.ok) {
throw new Error(`xAI OAuth refresh failed with HTTP ${response.status}`);
}
let payload;
try {
payload = await response.json();
} catch {
throw new Error('xAI OAuth refresh returned invalid JSON');
}
const access = nonEmptyString(payload?.access_token);
if (!access) {
throw new Error('xAI OAuth refresh returned no access token');
}
const expiresIn = payload?.expires_in ?? 3600;
if (typeof expiresIn !== 'number' || !Number.isFinite(expiresIn)) {
throw new Error('xAI OAuth refresh returned an invalid expiry');
}
const expires = Date.now() + expiresIn * 1000;
const refreshed = {
...entry,
type: 'oauth',
access,
refresh: nonEmptyString(payload?.refresh_token) ?? refreshToken,
expires
};
const auth = readAuthFile();
auth.xai = refreshed;
writeAuthFile(auth);
return refreshed;
})().finally(() => {
refreshPromise = null;
});
}
return refreshPromise;
};
const ensureFreshAccess = async (entry) => {
if (!tokenNeedsRefresh(entry)) return entry;
if (!nonEmptyString(entry.refresh)) {
throw new Error('xAI OAuth access token is expired and has no usable refresh token');
}
return refreshXaiOauth(entry);
};
const readVarint = (bytes, state) => {
let value = 0n;
for (let shift = 0n; state.index < bytes.length && shift < 64n; shift += 7n) {
const byte = bytes[state.index++];
if (shift === 63n && (byte & 0x7e) !== 0) return null;
value |= BigInt(byte & 0x7f) << shift;
if ((byte & 0x80) === 0) return value;
}
return null;
};
const samePath = (left, right) => left.length === right.length && left.every((value, index) => value === right[index]);
// CodexBar observes both the flat billing message and the response envelope.
const USAGE_PERCENT_PATHS = [[1], [1, 1]];
const hasPath = (paths, candidate) => paths.some((path) => samePath(path, candidate));
const scanProtobuf = (bytes, path = [], depth = 0, state = { index: 0, order: 0 }) => {
const fixed32Fields = [];
const varintFields = [];
while (state.index < bytes.length) {
const key = readVarint(bytes, state);
if (key === null || key === 0n) return false;
const fieldNumber = Number(key >> 3n);
const wireType = Number(key & 0x07n);
if (!fieldNumber || fieldNumber > 0x1fffffff) return false;
const fieldPath = [...path, fieldNumber];
if (wireType === 0) {
const value = readVarint(bytes, state);
if (value === null) return false;
varintFields.push({ path: fieldPath, value });
continue;
}
if (wireType === 1) {
if (state.index + 8 > bytes.length) return false;
state.index += 8;
continue;
}
if (wireType === 2) {
const length = readVarint(bytes, state);
if (length === null || length > BigInt(bytes.length - state.index)) return false;
const end = state.index + Number(length);
if (depth >= 4 && length !== 0n) return false;
if (depth < 4) {
const nestedState = { index: 0, order: state.order };
const nested = scanProtobuf(bytes.slice(state.index, end), fieldPath, depth + 1, nestedState);
if (nested === false) return false;
fixed32Fields.push(...nested.fixed32Fields);
varintFields.push(...nested.varintFields);
state.order = nestedState.order;
}
state.index = end;
continue;
}
if (wireType === 5) {
if (state.index + 4 > bytes.length) return false;
const value = Buffer.from(bytes.slice(state.index, state.index + 4)).readFloatLE(0);
fixed32Fields.push({ path: fieldPath, value, order: state.order++ });
state.index += 4;
continue;
}
return false;
}
return { fixed32Fields, varintFields };
};
const parseFrames = (bytes) => {
if (bytes.length < 5 || (bytes[0] & 0x7f) !== 0) return null;
const messages = [];
const trailerStatuses = [];
let trailerStarted = false;
let index = 0;
while (index < bytes.length) {
if (index + 5 > bytes.length) return false;
const flags = bytes[index++];
if ((flags & 0x7f) !== 0) return false;
const isTrailer = (flags & 0x80) !== 0;
if (trailerStarted && !isTrailer) return false;
const length = (bytes[index] * 0x1000000)
+ (bytes[index + 1] << 16)
+ (bytes[index + 2] << 8)
+ bytes[index + 3];
index += 4;
const end = index + length;
if (end > bytes.length) return false;
const payload = bytes.slice(index, end);
if (isTrailer) {
trailerStarted = true;
const status = parseGrpcTrailerStatus(payload);
if (status === null) return false;
trailerStatuses.push(status);
} else {
messages.push(payload);
}
index = end;
}
return { messages, trailerStatuses };
};
const parseGrpcTrailerStatus = (bytes) => {
let text;
try {
text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
} catch {
return null;
}
let status = null;
for (const line of text.split(/\r?\n/)) {
if (!line) continue;
const separator = line.indexOf(':');
if (separator <= 0) return null;
const key = line.slice(0, separator).trim().toLowerCase();
if (!key) return null;
if (key !== 'grpc-status') continue;
if (status !== null) return null;
const rawStatus = line.slice(separator + 1).trim();
if (!/^\d+$/.test(rawStatus)) return null;
status = Number(rawStatus);
if (!Number.isSafeInteger(status)) return null;
}
return status;
};
const looksLikeProtobuf = (bytes) => {
if (!bytes.length) return false;
const fieldNumber = bytes[0] >> 3;
const wireType = bytes[0] & 0x07;
return fieldNumber > 0 && [0, 1, 2, 5].includes(wireType);
};
const parseUsage = (bytes) => {
const framed = parseFrames(bytes);
if (framed === false) throw new Error('xAI billing returned malformed gRPC-web framing');
const payloads = framed ? framed.messages : (looksLikeProtobuf(bytes) ? [bytes] : []);
if (framed) {
for (const status of framed.trailerStatuses) {
if (status !== 0) throw new Error(`xAI billing RPC failed with status ${status}`);
}
}
if (payloads.length === 0) throw new Error('xAI billing returned an empty protobuf response');
const scan = { fixed32Fields: [], varintFields: [] };
for (const payload of payloads) {
const result = scanProtobuf(payload);
if (result === false) throw new Error('xAI billing returned malformed protobuf');
scan.fixed32Fields.push(...result.fixed32Fields);
scan.varintFields.push(...result.varintFields);
}
const percentages = scan.fixed32Fields
.filter((field) => (
hasPath(USAGE_PERCENT_PATHS, field.path)
&& Number.isFinite(field.value)
&& field.value >= 0
&& field.value <= 100
))
.sort((left, right) => left.path.length - right.path.length || left.order - right.order);
const usedPercent = percentages.length > 0 ? percentages[0].value : null;
const resetCandidates = scan.varintFields
.filter((field) => field.value >= 1_700_000_000n && field.value <= 2_100_000_000n)
.map((field) => ({ ...field, seconds: Number(field.value) }))
.map((field) => ({ ...field, resetAt: field.seconds * 1000 }))
.filter((field) => field.resetAt > Date.now());
const preferredReset = resetCandidates.filter((field) => samePath(field.path, [1, 5, 1]));
const resetAt = (preferredReset.length > 0 ? preferredReset : resetCandidates)
.sort((left, right) => left.resetAt - right.resetAt)[0]?.resetAt ?? null;
const hasUsagePeriod = scan.varintFields.some((field) => (
(field.path.length >= 2 && field.path[0] === 1 && field.path[1] === 6)
|| (samePath(field.path, [1, 8, 1]) && (field.value === 1n || field.value === 2n))
));
if (usedPercent === null && scan.fixed32Fields.length === 0 && resetAt !== null && hasUsagePeriod) {
return { usedPercent: 0, resetAt };
}
if (usedPercent === null) throw new Error('xAI billing response had no usable current-period usage');
return { usedPercent, resetAt };
};
const fetchUsage = async (accessToken) => {
const response = await fetch(USAGE_URL, {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`,
Origin: 'https://grok.com',
Referer: 'https://grok.com/?_s=usage',
Accept: '*/*',
'Content-Type': 'application/grpc-web+proto',
'x-grpc-web': '1',
'x-user-agent': 'connect-es/2.1.1',
'User-Agent': 'OpenChamber'
},
body: EMPTY_GRPC_WEB_BODY,
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
});
const headerStatus = response.headers.get('grpc-status');
if (headerStatus !== null) {
if (!/^\d+$/.test(headerStatus.trim())) throw new Error('xAI billing returned malformed gRPC status');
const status = Number(headerStatus.trim());
if (!Number.isSafeInteger(status)) throw new Error('xAI billing returned malformed gRPC status');
if (status !== 0) throw new Error(`xAI billing RPC failed with status ${status}`);
}
if (!response.ok) throw new Error(`xAI billing request failed with HTTP ${response.status}`);
return parseUsage(new Uint8Array(await response.arrayBuffer()));
};
export const isConfigured = () => Boolean(readXaiAuth().entry);
export const fetchQuota = async () => {
const { entry, error: authError } = readXaiAuth();
if (authError) {
return buildResult({
providerId,
providerName,
ok: false,
configured: true,
error: authError
});
}
if (!entry) {
return buildResult({
providerId,
providerName,
ok: false,
configured: false,
error: 'Not configured'
});
}
try {
const freshEntry = await ensureFreshAccess(entry);
const accessToken = nonEmptyString(freshEntry.access);
if (!accessToken) throw new Error('xAI OAuth entry has no usable access token');
const usage = await fetchUsage(accessToken);
return buildResult({
providerId,
providerName,
ok: true,
configured: true,
usage: {
windows: {
billing_cycle: toUsageWindow({
usedPercent: usage.usedPercent,
windowSeconds: null,
resetAt: usage.resetAt
})
}
}
});
} catch (error) {
return buildResult({
providerId,
providerName,
ok: false,
configured: true,
error: error instanceof Error ? error.message : 'Request failed'
});
}
};