diff --git a/packages/ui/src/components/sections/usage/UsagePage.tsx b/packages/ui/src/components/sections/usage/UsagePage.tsx
index 4a83e8b7..d1e5a412 100644
--- a/packages/ui/src/components/sections/usage/UsagePage.tsx
+++ b/packages/ui/src/components/sections/usage/UsagePage.tsx
@@ -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 = () => {
{t('settings.usage.page.state.noData')}
)}
- {error && (
+ {(error || selectedProviderError) && (
{t('settings.usage.page.state.refreshFailedTitle')}
-
{error}
+
{error ?? selectedProviderError}
)}
diff --git a/packages/ui/src/lib/quota/providers/index.ts b/packages/ui/src/lib/quota/providers/index.ts
index 5d1798c3..96a4906c 100644
--- a/packages/ui/src/lib/quota/providers/index.ts
+++ b/packages/ui/src/lib/quota/providers/index.ts
@@ -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' },
];
diff --git a/packages/ui/src/types/quota.ts b/packages/ui/src/types/quota.ts
index 365f588d..fc634a78 100644
--- a/packages/ui/src/types/quota.ts
+++ b/packages/ui/src/types/quota.ts
@@ -18,7 +18,8 @@ export type QuotaProviderId =
| 'opencode-go'
| 'crof'
| 'deepseek'
- | 'neuralwatt';
+ | 'neuralwatt'
+ | 'xai';
export interface UsageWindow {
usedPercent: number | null;
diff --git a/packages/vscode/src/opencodeAuth.ts b/packages/vscode/src/opencodeAuth.ts
index cbac7e14..06c2c40e 100644
--- a/packages/vscode/src/opencodeAuth.ts
+++ b/packages/vscode/src/opencodeAuth.ts
@@ -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;
+export type AuthEntry = Record;
type AuthFile = Record;
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');
diff --git a/packages/vscode/src/quotaProviders.ts b/packages/vscode/src/quotaProviders.ts
index f759e351..7aa3bd73 100644
--- a/packages/vscode/src/quotaProviders.ts
+++ b/packages/vscode/src/quotaProviders.ts
@@ -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;
type AuthFile = Record;
@@ -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 & {
+ type: 'oauth';
+ access?: string;
+ refresh?: string;
+ expires?: unknown;
+};
+
+let xaiRefreshPromise: Promise | 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;
+ 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 => {
+ 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 | 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 => {
+ 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();
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 => {
}
};
+const fetchXaiQuota = async (): Promise => {
+ 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 => {
switch (providerId) {
case 'claude':
@@ -2350,6 +2751,8 @@ export const fetchQuotaForProvider = async (providerId: string): Promise {
+ 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'
+ });
+ }
+};