feat(quota): add Crof and NeuralWatt quota providers (#2415)

This commit is contained in:
pablogonzalez
2026-07-26 17:57:53 +03:00
committed by GitHub
parent 023ec2362e
commit e2b0a113b8
13 changed files with 1330 additions and 1 deletions
+367
View File
@@ -0,0 +1,367 @@
import { afterEach, beforeEach, describe, test } from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
// readAuthFile reads ~/.local/share/opencode/auth.json via fs.readFileSync.
// Stub fs to serve a known auth entry so the providers treat themselves as
// configured and proceed straight to fetch.
const ORIGINAL_FS = { ...fs };
const AUTH = JSON.stringify({
crof: { key: 'test-token' },
neuralwatt: { key: 'test-token' },
});
((fs as unknown) as { existsSync: () => boolean }).existsSync = () => true;
((fs as unknown) as { readFileSync: () => string }).readFileSync = () => AUTH;
import { fetchQuotaForProvider } from './quotaProviders';
type MockResponseInit = { ok?: boolean; status?: number };
const mockResponse = (body: unknown, init: MockResponseInit = {}): Response => ({
ok: 'ok' in init ? init.ok! : true,
status: init.status ?? 200,
json: async () => body,
} as unknown as Response);
// Documented NeuralWatt payload from https://portal.neuralwatt.com/docs/api/quota.
// plan="standard", kwh_included=20.0, kwh_used=13.9023.
const DOCUMENTED_SUBSCRIPTION_PAYLOAD = {
snapshot_at: '2026-04-16T18:30:00Z',
balance: { credits_remaining_usd: 32.6774, total_credits_usd: 52.34, credits_used_usd: 19.6626, accounting_method: 'energy' },
usage: {
lifetime: { cost_usd: 243.9145, requests: 37801, tokens: 1235477176, energy_kwh: 15.6009 },
current_month: { cost_usd: 160.1463, requests: 23902, tokens: 1116658995, energy_kwh: 9.7278 },
},
limits: { overage_limit_usd: null, rate_limit_tier: 'standard' },
subscription: {
plan: 'standard',
status: 'active',
billing_interval: 'year',
current_period_start: '2026-04-11T05:05:25Z',
current_period_end: '2027-04-11T05:05:25Z',
auto_renew: true,
kwh_included: 20.0,
kwh_used: 13.9023,
kwh_remaining: 6.0977,
in_overage: false,
},
key: { name: 'my-production-key', allowance: null },
} as const;
let ORIGINAL_FETCH: typeof globalThis.fetch;
beforeEach(() => {
ORIGINAL_FETCH = globalThis.fetch;
});
afterEach(() => {
globalThis.fetch = ORIGINAL_FETCH;
});
const stubFetchReturning = (resolver: () => Promise<unknown>): void => {
globalThis.fetch = (async () => resolver()) as typeof fetch;
};
const stubFetchFailing = (json: () => Promise<unknown>, init: MockResponseInit): void => {
globalThis.fetch = (async () => ({ json, ...init }) as unknown as Response) as typeof fetch;
};
describe('Crof quota provider (VS Code parity)', () => {
test('reports credits balance as valueLabel with null percent', async () => {
stubFetchReturning(() => Promise.resolve(mockResponse({ usable_requests: 450, credits: 12.3456 })));
const result = await fetchQuotaForProvider('crof');
assert.equal(result.ok, true);
assert.equal(result.providerId, 'crof');
assert.equal(result.usage!.windows.credits!.usedPercent, null);
assert.equal(result.usage!.windows.credits!.valueLabel, '$12.35');
});
test('tolerates missing credits field', async () => {
stubFetchReturning(() => Promise.resolve(mockResponse({ usable_requests: 0 })));
const result = await fetchQuotaForProvider('crof');
assert.equal(result.ok, true);
assert.equal(result.usage!.windows.credits!.valueLabel, undefined);
assert.equal(result.usage!.windows.credits!.usedPercent, null);
});
test('maps 401 to session-expired with CrofAI branding', async () => {
stubFetchFailing(async () => ({}), { ok: false, status: 401 });
const result = await fetchQuotaForProvider('crof');
assert.equal(result.ok, false);
assert.equal(result.configured, true);
assert.equal(result.error, 'Session expired — please re-authenticate with CrofAI');
});
test('reports invalid-response on JSON parse failure', async () => {
globalThis.fetch = (async () => ({
ok: true,
status: 200,
json: async () => { throw new SyntaxError('Unexpected token'); },
}) as unknown as Response) as typeof fetch;
const result = await fetchQuotaForProvider('crof');
assert.equal(result.ok, false);
assert.equal(result.error, 'Invalid response from provider');
});
});
describe('NeuralWatt quota provider (VS Code parity)', () => {
test('builds subscription window keyed by plan name (windowSeconds null)', async () => {
stubFetchReturning(() => Promise.resolve(mockResponse(DOCUMENTED_SUBSCRIPTION_PAYLOAD)));
const result = await fetchQuotaForProvider('neuralwatt');
assert.equal(result.ok, true);
assert.equal(result.providerId, 'neuralwatt');
// Subscription window is keyed by the plan name; windowSeconds is null
// because the API exposes no kWh window start to derive duration from.
const window = result.usage!.windows.standard;
assert.ok(window, 'subscription window should be defined');
assert.ok(Math.abs((window.usedPercent as number) - (13.9023 / 20.0) * 100) < 1e-2);
assert.equal(window.windowSeconds, null);
assert.equal(window.resetAt, Date.parse('2027-04-11T05:05:25Z'));
// allowance is null → credits_balance also surfaced
assert.ok(result.usage!.windows.credits_balance, 'credits_balance should be defined');
assert.equal(result.usage!.windows.credits_balance!.valueLabel, '$32.68');
});
test('falls back to plan_limit title when plan is missing', async () => {
const payload = {
...DOCUMENTED_SUBSCRIPTION_PAYLOAD,
subscription: { ...DOCUMENTED_SUBSCRIPTION_PAYLOAD.subscription, plan: null },
};
stubFetchReturning(() => Promise.resolve(mockResponse(payload)));
const result = await fetchQuotaForProvider('neuralwatt');
assert.ok(result.usage!.windows.plan_limit);
assert.ok(Math.abs((result.usage!.windows.plan_limit!.usedPercent as number) - (13.9023 / 20.0) * 100) < 1e-2);
});
test('marks in-overage subscription as 100%, still shows credits', async () => {
const payload = {
...DOCUMENTED_SUBSCRIPTION_PAYLOAD,
subscription: { ...DOCUMENTED_SUBSCRIPTION_PAYLOAD.subscription, in_overage: true, kwh_used: 25.0 },
};
stubFetchReturning(() => Promise.resolve(mockResponse(payload)));
const result = await fetchQuotaForProvider('neuralwatt');
const window = result.usage!.windows.standard;
assert.ok(window);
assert.equal(window!.usedPercent, 100);
assert.equal(result.usage!.windows.credits_balance!.valueLabel, '$32.68');
});
test('surfaces subscription and allowance windows (allowance keyed by period, key name in valueLabel)', async () => {
const payload = {
...DOCUMENTED_SUBSCRIPTION_PAYLOAD,
balance: { credits_remaining_usd: 200 },
key: {
name: 'Prod',
allowance: { limit_usd: 100, period: 'monthly', spent_usd: 25, blocked: false, reset_at: '2026-08-01T00:00:00Z' },
},
};
stubFetchReturning(() => Promise.resolve(mockResponse(payload)));
const result = await fetchQuotaForProvider('neuralwatt');
const subWindow = result.usage!.windows.standard;
assert.ok(subWindow);
assert.ok(Math.abs((subWindow!.usedPercent as number) - (13.9023 / 20.0) * 100) < 1e-2);
// Allowance window is keyed by the localized period label ("monthly");
// key name flows through valueLabel for identification.
const allowWindow = result.usage!.windows.monthly;
assert.ok(allowWindow);
assert.equal(allowWindow!.usedPercent, 25);
assert.equal(allowWindow!.valueLabel, 'Prod');
assert.equal(allowWindow!.resetAt, Date.parse('2026-08-01T00:00:00Z'));
assert.equal(result.usage!.windows.credits_balance, undefined);
});
test('uses allowance effective limit = min(limit, credits_remaining + spent)', async () => {
const payload = {
balance: { credits_remaining_usd: 30 },
subscription: null,
key: {
name: 'prod-key',
allowance: { limit_usd: 100, period: 'monthly', spent_usd: 25, blocked: false, reset_at: '2026-08-01T00:00:00Z' },
},
};
stubFetchReturning(() => Promise.resolve(mockResponse(payload)));
const result = await fetchQuotaForProvider('neuralwatt');
const window = result.usage!.windows.monthly;
assert.ok(window);
// effectiveLimit = min(100, 30+25) = 55; usedPercent = 25/55 * 100 ≈ 45.4545
assert.ok(Math.abs((window!.usedPercent as number) - (25 / 55) * 100) < 1e-2);
assert.equal(window!.windowSeconds, 30 * 86400);
assert.equal(window!.resetAt, Date.parse('2026-08-01T00:00:00Z'));
assert.equal(window!.valueLabel, 'prod-key');
assert.equal(result.usage!.windows.credits_balance, undefined);
});
test('binds allowance ceiling to limit when limit < credits_remaining + spent', async () => {
const payload = {
balance: { credits_remaining_usd: 200 },
subscription: null,
key: {
name: 'prod-key',
allowance: { limit_usd: 100, period: 'monthly', spent_usd: 25, blocked: false, reset_at: '2026-08-01T00:00:00Z' },
},
};
stubFetchReturning(() => Promise.resolve(mockResponse(payload)));
const result = await fetchQuotaForProvider('neuralwatt');
const window = result.usage!.windows.monthly;
assert.ok(window);
assert.equal(window!.usedPercent, 25);
});
test('uses weekly as the allowance key when period is weekly', async () => {
const payload = {
balance: { credits_remaining_usd: 200 },
subscription: null,
key: {
name: 'Prod',
allowance: { limit_usd: 100, period: 'weekly', spent_usd: 20, blocked: false, reset_at: '2026-07-04T00:00:00Z' },
},
};
stubFetchReturning(() => Promise.resolve(mockResponse(payload)));
const result = await fetchQuotaForProvider('neuralwatt');
const window = result.usage!.windows.weekly;
assert.ok(window);
assert.equal(window!.windowSeconds, 604800);
assert.equal(window!.resetAt, Date.parse('2026-07-04T00:00:00Z'));
assert.equal(window!.valueLabel, 'Prod');
});
test('uses daily as the allowance key when period is daily', async () => {
const payload = {
balance: { credits_remaining_usd: 200 },
subscription: null,
key: {
name: 'Prod',
allowance: { limit_usd: 10, period: 'daily', spent_usd: 2, blocked: false, reset_at: '2026-07-04T00:00:00Z' },
},
};
stubFetchReturning(() => Promise.resolve(mockResponse(payload)));
const result = await fetchQuotaForProvider('neuralwatt');
const window = result.usage!.windows.daily;
assert.ok(window);
assert.equal(window!.windowSeconds, 86400);
assert.equal(window!.resetAt, Date.parse('2026-07-04T00:00:00Z'));
});
test('falls back to billing_cycle when allowance period is missing or unknown', async () => {
const payload = {
balance: { credits_remaining_usd: 200 },
subscription: null,
key: {
name: 'Prod',
allowance: { limit_usd: 100, period: 'fortnightly', spent_usd: 25, blocked: false, reset_at: '2026-08-01T00:00:00Z' },
},
};
stubFetchReturning(() => Promise.resolve(mockResponse(payload)));
const result = await fetchQuotaForProvider('neuralwatt');
const window = result.usage!.windows.billing_cycle;
assert.ok(window);
assert.equal(window!.usedPercent, 25);
});
test('marks blocked allowance as 100% with valueLabel set', async () => {
const payload = {
balance: { credits_remaining_usd: 30 },
subscription: null,
key: {
name: 'sample',
allowance: { limit_usd: 50, period: 'monthly', spent_usd: 10, blocked: true, reset_at: '2026-08-01T00:00:00Z' },
},
};
stubFetchReturning(() => Promise.resolve(mockResponse(payload)));
const result = await fetchQuotaForProvider('neuralwatt');
const window = result.usage!.windows.monthly;
assert.ok(window);
assert.equal(window!.usedPercent, 100);
assert.equal(window!.valueLabel, 'sample');
});
test('falls back to credits_balance when neither subscription nor allowance exists', async () => {
const payload = {
balance: { credits_remaining_usd: 32.6774 },
subscription: null,
key: { name: 'sample', allowance: null },
};
stubFetchReturning(() => Promise.resolve(mockResponse(payload)));
const result = await fetchQuotaForProvider('neuralwatt');
assert.equal(result.usage!.windows.credits_balance!.valueLabel, '$32.68');
assert.equal(result.usage!.windows.credits_balance!.usedPercent, null);
});
test('maps 401 to session-expired', async () => {
stubFetchFailing(async () => ({}), { ok: false, status: 401 });
const result = await fetchQuotaForProvider('neuralwatt');
assert.equal(result.ok, false);
assert.equal(result.error, 'Session expired — please re-authenticate with NeuralWatt');
});
test('reports invalid-response on JSON parse failure', async () => {
globalThis.fetch = (async () => ({
ok: true,
status: 200,
json: async () => { throw new SyntaxError('Unexpected token'); },
}) as unknown as Response) as typeof fetch;
const result = await fetchQuotaForProvider('neuralwatt');
assert.equal(result.ok, false);
assert.equal(result.error, 'Invalid response from provider');
});
test('returns no-quota-data on a 200 payload with no usable windows', async () => {
stubFetchReturning(() => Promise.resolve(mockResponse({
balance: { credits_remaining_usd: null },
subscription: null,
key: { name: 'sample', allowance: null },
})));
const result = await fetchQuotaForProvider('neuralwatt');
assert.equal(result.ok, false);
assert.equal(result.configured, true);
assert.equal(result.error, 'No quota data in response');
assert.equal(result.usage, null);
});
// Restore fs so other test files (which use the real auth file) are unaffected.
test('teardown: restore fs', () => {
const fsMock = fs as unknown as { existsSync: unknown; readFileSync: unknown };
fsMock.existsSync = ORIGINAL_FS.existsSync;
fsMock.readFileSync = ORIGINAL_FS.readFileSync;
});
});
+282
View File
@@ -112,6 +112,37 @@ type WaferPayload = {
plan_tier?: string;
};
type CrofPayload = {
usable_requests?: number | null;
credits?: number | string;
};
type NeuralwattPayload = {
balance?: {
credits_remaining_usd?: number | string;
};
subscription?: {
plan?: string;
billing_interval?: string;
current_period_start?: string;
current_period_end?: string;
kwh_included?: number | string;
kwh_used?: number | string;
in_overage?: boolean;
kwh_reset_date?: string;
} | null;
key?: {
name?: string;
allowance?: {
limit_usd?: number | string;
period?: string;
spent_usd?: number | string;
blocked?: boolean;
reset_at?: string;
} | null;
};
};
export type ProviderResult = {
providerId: string;
providerName: string;
@@ -441,6 +472,16 @@ export const listConfiguredQuotaProviders = () => {
configured.add('wafer');
}
const crofAuth = normalizeAuthEntry(getAuthEntry(auth, ['crof']));
if (crofAuth && ((crofAuth as Record<string, unknown>).key || (crofAuth as Record<string, unknown>).token)) {
configured.add('crof');
}
const neuralwattAuth = normalizeAuthEntry(getAuthEntry(auth, ['neuralwatt']));
if (neuralwattAuth && ((neuralwattAuth as Record<string, unknown>).key || (neuralwattAuth as Record<string, unknown>).token)) {
configured.add('neuralwatt');
}
return Array.from(configured);
};
@@ -1865,6 +1906,243 @@ const fetchWaferQuota = async (): Promise<ProviderResult> => {
}
};
const NEURALWATT_QUOTA_URL = 'https://api.neuralwatt.com/v1/quota';
// 30d month / 365d year are fixed approximations; real calendars vary but the
// window is for the UI's progress bar label, not billing decisions.
// Accepts both subscription (month/year) and allowance (monthly/weekly/daily) shapes.
const neuralwattWindowSeconds = (period: string | null | undefined): number | null => {
if (period === 'daily') return 86400;
if (period === 'weekly') return 604800;
if (period === 'monthly' || period === 'month') return 30 * 86400;
if (period === 'yearly' || period === 'year') return 365 * 86400;
return null;
};
const fetchNeuralwattQuota = async (): Promise<ProviderResult> => {
const auth = readAuthFile();
const entry = normalizeAuthEntry(getAuthEntry(auth, ['neuralwatt'])) as Record<string, unknown> | null;
const apiKey = (entry?.key as string | undefined) ?? (entry?.token as string | undefined);
if (!apiKey) {
return buildResult({
providerId: 'neuralwatt',
providerName: 'NeuralWatt',
ok: false,
configured: false,
error: 'Not configured',
});
}
const timeoutSignal = AbortSignal.timeout(15_000);
try {
const response = await fetch(NEURALWATT_QUOTA_URL, {
method: 'GET',
headers: {
Authorization: `Bearer ${apiKey}`,
'Accept-Encoding': 'identity',
},
signal: timeoutSignal,
});
if (!response.ok) {
return buildResult({
providerId: 'neuralwatt',
providerName: 'NeuralWatt',
ok: false,
configured: true,
error: response.status === 401
? 'Session expired — please re-authenticate with NeuralWatt'
: `API error: ${response.status}`,
});
}
const payload = await response.json() as NeuralwattPayload;
const subscription = payload?.subscription ?? null;
const inOverage = Boolean(subscription?.in_overage);
const allowance = payload?.key?.allowance ?? null;
const keyName = payload?.key?.name ?? null;
const creditsRemaining = toNumber(payload?.balance?.credits_remaining_usd);
const windows: Record<string, UsageWindow> = {};
if (subscription) {
const kwhIncluded = toNumber(subscription.kwh_included);
const kwhUsed = toNumber(subscription.kwh_used);
const plan = typeof subscription.plan === 'string' && subscription.plan.trim()
? subscription.plan.trim()
: null;
// Subscription window title is the plan name; subscription limits reset
// monthly even on annual billing plans, but the API exposes no kWh window
// start to derive windowSeconds — pass null rather than fabricating a guess.
const subKey = plan ?? 'plan_limit';
const usedPercent = inOverage
? 100
: (kwhIncluded !== null && kwhIncluded > 0 && kwhUsed !== null
? Math.max(0, Math.min(100, (kwhUsed / kwhIncluded) * 100))
: null);
const subResetAt = toTimestamp(subscription.kwh_reset_date) ?? toTimestamp(subscription.current_period_end);
windows[subKey] = toUsageWindow({
usedPercent,
windowSeconds: null,
resetAt: subResetAt,
});
}
if (allowance) {
const spent = toNumber(allowance.spent_usd);
const limit = toNumber(allowance.limit_usd);
// Credits wallet is reduced by each period's spend before the allowance cap
// bites, so the real ceiling is min(limit, creditsRemaining + spent).
const effectiveSpent = spent ?? 0;
const effectiveLimit = limit !== null && creditsRemaining !== null
? Math.min(limit, creditsRemaining + effectiveSpent)
: (limit ?? creditsRemaining);
const period = typeof allowance.period === 'string' && allowance.period.trim()
? allowance.period.trim()
: null;
const blocked = Boolean(allowance.blocked);
const usedPercent = blocked
? 100
: (spent !== null && effectiveLimit !== null && effectiveLimit > 0
? Math.max(0, Math.min(100, (spent / effectiveLimit) * 100))
: null);
// Window title is the localized period label (daily/weekly/monthly); key
// name is attached via valueLabel for identification (wafer precedent).
const periodKey = (period === 'daily' || period === 'weekly' || period === 'monthly' || period === 'month')
? (period === 'month' ? 'monthly' : period)
: 'billing_cycle';
const labelName = typeof keyName === 'string' && keyName.trim() ? keyName.trim() : null;
const resetAt = toTimestamp(allowance.reset_at);
const windowSeconds = period ? neuralwattWindowSeconds(period) : null;
windows[periodKey] = toUsageWindow({
usedPercent,
windowSeconds,
resetAt,
...(labelName ? { valueLabel: labelName } : {}),
});
} else if (creditsRemaining !== null) {
windows.credits_balance = toUsageWindow({
usedPercent: null,
windowSeconds: null,
resetAt: null,
valueLabel: `$${formatMoney(creditsRemaining)}`,
});
}
if (Object.keys(windows).length === 0) {
return buildResult({
providerId: 'neuralwatt',
providerName: 'NeuralWatt',
ok: false,
configured: true,
error: 'No quota data in response',
});
}
return buildResult({
providerId: 'neuralwatt',
providerName: 'NeuralWatt',
ok: true,
configured: true,
usage: { windows },
});
} catch (error) {
const isTimeout = error instanceof DOMException && error.name === 'AbortError' && timeoutSignal.aborted;
const isParseError = error instanceof SyntaxError;
return buildResult({
providerId: 'neuralwatt',
providerName: 'NeuralWatt',
ok: false,
configured: true,
error: isTimeout
? 'Request timed out'
: isParseError
? 'Invalid response from provider'
: (error instanceof Error ? error.message : 'Request failed'),
});
}
};
const CROF_USAGE_URL = 'https://crof.ai/usage_api/';
const fetchCrofQuota = async (): Promise<ProviderResult> => {
const auth = readAuthFile();
const entry = normalizeAuthEntry(getAuthEntry(auth, ['crof'])) as Record<string, unknown> | null;
const apiKey = (entry?.key as string | undefined) ?? (entry?.token as string | undefined);
if (!apiKey) {
return buildResult({
providerId: 'crof',
providerName: 'CrofAI',
ok: false,
configured: false,
error: 'Not configured',
});
}
const timeoutSignal = AbortSignal.timeout(15_000);
try {
const response = await fetch(CROF_USAGE_URL, {
method: 'GET',
headers: {
Authorization: `Bearer ${apiKey}`,
'Accept-Encoding': 'identity',
},
signal: timeoutSignal,
});
if (!response.ok) {
return buildResult({
providerId: 'crof',
providerName: 'CrofAI',
ok: false,
configured: true,
error: response.status === 401
? 'Session expired — please re-authenticate with CrofAI'
: `API error: ${response.status}`,
});
}
const payload = await response.json() as CrofPayload;
const credits = toNumber(payload?.credits);
const valueLabel = credits !== null ? `$${formatMoney(credits)}` : null;
const windows: Record<string, UsageWindow> = {
credits: toUsageWindow({
usedPercent: null,
windowSeconds: null,
resetAt: null,
valueLabel,
}),
};
return buildResult({
providerId: 'crof',
providerName: 'CrofAI',
ok: true,
configured: true,
usage: { windows },
});
} catch (error) {
const isTimeout = error instanceof DOMException && error.name === 'AbortError' && timeoutSignal.aborted;
const isParseError = error instanceof SyntaxError;
return buildResult({
providerId: 'crof',
providerName: 'CrofAI',
ok: false,
configured: true,
error: isTimeout
? 'Request timed out'
: isParseError
? 'Invalid response from provider'
: (error instanceof Error ? error.message : 'Request failed'),
});
}
};
export const fetchQuotaForProvider = async (providerId: string): Promise<ProviderResult> => {
switch (providerId) {
case 'claude':
@@ -1906,6 +2184,10 @@ export const fetchQuotaForProvider = async (providerId: string): Promise<Provide
}
case 'cursor':
return fetchCursorQuota();
case 'crof':
return fetchCrofQuota();
case 'neuralwatt':
return fetchNeuralwattQuota();
default:
return buildResult({
providerId,